mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-23 16:25:22 +03:00
Validate the contents of the VTX Json when loading (#1753)
Validate the contents of the VTX Json when loading
This commit is contained in:
commit
0c00a80b8e
5 changed files with 264 additions and 42 deletions
|
@ -41,6 +41,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^3.5.5",
|
"bluebird": "^3.5.5",
|
||||||
|
"djv": "^2.1.3-alpha.0",
|
||||||
"i18next": "^18.0.1",
|
"i18next": "^18.0.1",
|
||||||
"i18next-xhr-backend": "^3.1.1",
|
"i18next-xhr-backend": "^3.1.1",
|
||||||
"inflection": "1.12.0",
|
"inflection": "1.12.0",
|
||||||
|
|
|
@ -10,6 +10,7 @@ TABS.vtx = {
|
||||||
VTXTABLE_POWERLEVEL_LIST: [],
|
VTXTABLE_POWERLEVEL_LIST: [],
|
||||||
analyticsChanges: {},
|
analyticsChanges: {},
|
||||||
updating: true,
|
updating: true,
|
||||||
|
env: new djv(),
|
||||||
};
|
};
|
||||||
|
|
||||||
TABS.vtx.initialize = function (callback) {
|
TABS.vtx.initialize = function (callback) {
|
||||||
|
@ -98,6 +99,35 @@ TABS.vtx.initialize = function (callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validates the vtxConfig object against a JSON Schema
|
||||||
|
function validateVtxJson(vtxConfig, callback_valid, callback_error) {
|
||||||
|
|
||||||
|
// At minimum the version must be defined
|
||||||
|
if (!vtxConfig.version) {
|
||||||
|
console.error("Validation against schema failed, version missing");
|
||||||
|
callback_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load schema
|
||||||
|
const urlVtxSchema = chrome.runtime.getURL(`resources/jsonschema/vtxconfig_schema-${vtxConfig.version}.json`);
|
||||||
|
|
||||||
|
fetch(urlVtxSchema)
|
||||||
|
.then(response => response.json())
|
||||||
|
.catch(error => console.error('Error fetching VTX Schema:', error))
|
||||||
|
.then(schemaJson => {
|
||||||
|
|
||||||
|
let valid = false;
|
||||||
|
if (schemaJson !== undefined) {
|
||||||
|
// Validate
|
||||||
|
valid = (TABS.vtx.env.validate(schemaJson, vtxConfig) === undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Validation against schema result:", valid);
|
||||||
|
valid ? callback_valid() : callback_error();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Emulates the MSP read from a vtxConfig object (JSON)
|
// Emulates the MSP read from a vtxConfig object (JSON)
|
||||||
function read_vtx_config_json(vtxConfig, vtxcallback_after_read) {
|
function read_vtx_config_json(vtxConfig, vtxcallback_after_read) {
|
||||||
|
|
||||||
|
@ -658,16 +688,32 @@ TABS.vtx.initialize = function (callback) {
|
||||||
|
|
||||||
let text = e.target.result;
|
let text = e.target.result;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
let vtxConfig = JSON.parse(text);
|
let vtxConfig = JSON.parse(text);
|
||||||
read_vtx_config_json(vtxConfig, load_html);
|
|
||||||
|
|
||||||
TABS.vtx.vtxTableSavePending = true;
|
validateVtxJson(
|
||||||
|
vtxConfig,
|
||||||
|
function() {
|
||||||
|
|
||||||
self.analyticsChanges['VtxTableLoadFromClipboard'] = undefined;
|
// JSON is valid
|
||||||
self.analyticsChanges['VtxTableLoadFromFile'] = file.name;
|
read_vtx_config_json(vtxConfig, load_html);
|
||||||
|
|
||||||
console.log('Load VTX file end');
|
TABS.vtx.vtxTableSavePending = true;
|
||||||
GUI.log(i18n.getMessage('vtxLoadFileOk'));
|
|
||||||
|
self.analyticsChanges['VtxTableLoadFromClipboard'] = undefined;
|
||||||
|
self.analyticsChanges['VtxTableLoadFromFile'] = file.name;
|
||||||
|
|
||||||
|
console.log('Load VTX file end');
|
||||||
|
GUI.log(i18n.getMessage('vtxLoadFileOk'));
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
|
||||||
|
// JSON is NOT valid
|
||||||
|
console.error('VTX Config from file failed validation against schema');
|
||||||
|
GUI.log(i18n.getMessage('vtxLoadFileKo'));
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed loading VTX file config');
|
console.error('Failed loading VTX file config');
|
||||||
|
@ -694,15 +740,29 @@ TABS.vtx.initialize = function (callback) {
|
||||||
console.log('Pasted content: ', text);
|
console.log('Pasted content: ', text);
|
||||||
|
|
||||||
let vtxConfig = JSON.parse(text);
|
let vtxConfig = JSON.parse(text);
|
||||||
read_vtx_config_json(vtxConfig, load_html);
|
|
||||||
|
|
||||||
TABS.vtx.vtxTableSavePending = true;
|
validateVtxJson(
|
||||||
|
vtxConfig,
|
||||||
|
function() {
|
||||||
|
|
||||||
self.analyticsChanges['VtxTableLoadFromFile'] = undefined;
|
// JSON is valid
|
||||||
self.analyticsChanges['VtxTableLoadFromClipboard'] = text.length;
|
read_vtx_config_json(vtxConfig, load_html);
|
||||||
|
|
||||||
console.log('Load VTX clipboard end');
|
TABS.vtx.vtxTableSavePending = true;
|
||||||
GUI.log(i18n.getMessage('vtxLoadClipboardOk'));
|
|
||||||
|
self.analyticsChanges['VtxTableLoadFromFile'] = undefined;
|
||||||
|
self.analyticsChanges['VtxTableLoadFromClipboard'] = text.length;
|
||||||
|
|
||||||
|
console.log('Load VTX clipboard end');
|
||||||
|
GUI.log(i18n.getMessage('vtxLoadClipboardOk'));
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
|
||||||
|
// JSON is NOT valid
|
||||||
|
GUI.log(i18n.getMessage('vtxLoadClipboardKo'));
|
||||||
|
console.error('VTX Config from clipboard failed validation against schema');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
GUI.log(i18n.getMessage('vtxLoadClipboardKo'));
|
GUI.log(i18n.getMessage('vtxLoadClipboardKo'));
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
<script type="text/javascript" src="./node_modules/jquery/dist/jquery.min.js"></script>
|
<script type="text/javascript" src="./node_modules/jquery/dist/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="./node_modules/jbox/dist/jBox.min.js"></script>
|
<script type="text/javascript" src="./node_modules/jbox/dist/jBox.min.js"></script>
|
||||||
<script type="text/javascript" src="./node_modules/jquery-ui-npm/jquery-ui.min.js"></script>
|
<script type="text/javascript" src="./node_modules/jquery-ui-npm/jquery-ui.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/djv/djv.js"></script>
|
||||||
<script type="text/javascript" src="./js/libraries/d3.min.js"></script>
|
<script type="text/javascript" src="./js/libraries/d3.min.js"></script>
|
||||||
<script type="text/javascript" src="./js/libraries/jquery.nouislider.all.min.js"></script>
|
<script type="text/javascript" src="./js/libraries/jquery.nouislider.all.min.js"></script>
|
||||||
<script type="text/javascript" src="./js/libraries/three/three.min.js"></script>
|
<script type="text/javascript" src="./js/libraries/three/three.min.js"></script>
|
||||||
|
|
148
src/resources/jsonschema/vtxconfig_schema-1.0.json
Normal file
148
src/resources/jsonschema/vtxconfig_schema-1.0.json
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
{
|
||||||
|
"definitions": {},
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "http://example.com/root.json",
|
||||||
|
"type": "object",
|
||||||
|
"title": "The Root Schema",
|
||||||
|
"required": [
|
||||||
|
"description",
|
||||||
|
"version",
|
||||||
|
"vtx_table"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"$id": "#/properties/description",
|
||||||
|
"type": "string",
|
||||||
|
"title": "The Description Schema",
|
||||||
|
"default": "",
|
||||||
|
"examples": [
|
||||||
|
"Betaflight VTX Config file for SmartAudio 2.0 (US version)"
|
||||||
|
],
|
||||||
|
"pattern": "^(.*)$"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"$id": "#/properties/version",
|
||||||
|
"type": "string",
|
||||||
|
"title": "The Version Schema",
|
||||||
|
"default": "",
|
||||||
|
"examples": [
|
||||||
|
"1.0"
|
||||||
|
],
|
||||||
|
"pattern": "^(.*)$"
|
||||||
|
},
|
||||||
|
"vtx_table": {
|
||||||
|
"$id": "#/properties/vtx_table",
|
||||||
|
"type": "object",
|
||||||
|
"title": "The Vtx_table Schema",
|
||||||
|
"required": [
|
||||||
|
"bands_list",
|
||||||
|
"powerlevels_list"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"bands_list": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list",
|
||||||
|
"type": "array",
|
||||||
|
"title": "The Bands_list Schema",
|
||||||
|
"items": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list/items",
|
||||||
|
"type": "object",
|
||||||
|
"title": "The Items Schema",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"letter",
|
||||||
|
"is_factory_band",
|
||||||
|
"frequencies"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list/items/properties/name",
|
||||||
|
"type": "string",
|
||||||
|
"title": "The Name Schema",
|
||||||
|
"default": "",
|
||||||
|
"examples": [
|
||||||
|
"BOSCAM_A"
|
||||||
|
],
|
||||||
|
"pattern": "^(.*)$"
|
||||||
|
},
|
||||||
|
"letter": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list/items/properties/letter",
|
||||||
|
"type": "string",
|
||||||
|
"title": "The Letter Schema",
|
||||||
|
"default": "",
|
||||||
|
"examples": [
|
||||||
|
"A"
|
||||||
|
],
|
||||||
|
"pattern": "^(.*)$"
|
||||||
|
},
|
||||||
|
"is_factory_band": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list/items/properties/is_factory_band",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "The Is_factory_band Schema",
|
||||||
|
"default": false,
|
||||||
|
"examples": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"frequencies": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list/items/properties/frequencies",
|
||||||
|
"type": "array",
|
||||||
|
"title": "The Frequencies Schema",
|
||||||
|
"items": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/bands_list/items/properties/frequencies/items",
|
||||||
|
"type": "integer",
|
||||||
|
"title": "The Items Schema",
|
||||||
|
"default": 0,
|
||||||
|
"examples": [
|
||||||
|
5865,
|
||||||
|
5845,
|
||||||
|
5825,
|
||||||
|
5805,
|
||||||
|
5785,
|
||||||
|
5765,
|
||||||
|
5745,
|
||||||
|
5725
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"powerlevels_list": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/powerlevels_list",
|
||||||
|
"type": "array",
|
||||||
|
"title": "The Powerlevels_list Schema",
|
||||||
|
"items": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/powerlevels_list/items",
|
||||||
|
"type": "object",
|
||||||
|
"title": "The Items Schema",
|
||||||
|
"required": [
|
||||||
|
"value",
|
||||||
|
"label"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"value": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/powerlevels_list/items/properties/value",
|
||||||
|
"type": "integer",
|
||||||
|
"title": "The Value Schema",
|
||||||
|
"default": 0,
|
||||||
|
"examples": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"$id": "#/properties/vtx_table/properties/powerlevels_list/items/properties/label",
|
||||||
|
"type": "string",
|
||||||
|
"title": "The Label Schema",
|
||||||
|
"default": "",
|
||||||
|
"examples": [
|
||||||
|
"25 "
|
||||||
|
],
|
||||||
|
"pattern": "^(.*)$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
yarn.lock
12
yarn.lock
|
@ -9,6 +9,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
|
"@korzio/djv-draft-04@^2.0.1":
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@korzio/djv-draft-04/-/djv-draft-04-2.0.1.tgz#2984289426cac5ed622b26a58c3af8584aefbdfe"
|
||||||
|
integrity sha512-MeTVcNsfCIYxK6T7jW1sroC7dBAb4IfLmQe6RoCqlxHN5NFkzNpgdnBPR+/0D2wJDUJHM9s9NQv+ouhxKjvUjg==
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.3":
|
"@nodelib/fs.scandir@2.1.3":
|
||||||
version "2.1.3"
|
version "2.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
|
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
|
||||||
|
@ -1335,6 +1340,13 @@ dir-glob@^3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
|
djv@^2.1.3-alpha.0:
|
||||||
|
version "2.1.3-alpha.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/djv/-/djv-2.1.3-alpha.0.tgz#554daa91f22e0e8e9f48c9550766a6c07e8ce180"
|
||||||
|
integrity sha512-vrKAFr/wbhMjfqo+eoXZRIx/6YbN1DSZlxUsE3tHDPYB0zWRtOBhqmKbcgCjfP3+KevqidBGn2jNRnqRhjIzYg==
|
||||||
|
optionalDependencies:
|
||||||
|
"@korzio/djv-draft-04" "^2.0.1"
|
||||||
|
|
||||||
dom-serialize@^2.2.0:
|
dom-serialize@^2.2.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
|
resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue