From d40ab53c35c9edab4f2ddff4b3db44ccb4abd6e0 Mon Sep 17 00:00:00 2001 From: Scott Bender Date: Mon, 23 Nov 2020 16:49:06 -0500 Subject: [PATCH] feature: add meta deltas support to FullSignalK (#597) --- src/fullsignalk.js | 33 ++++++++++++++++++++---------- src/index.js | 50 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/fullsignalk.js b/src/fullsignalk.js index cf68e3c57..1541e1a86 100644 --- a/src/fullsignalk.js +++ b/src/fullsignalk.js @@ -105,7 +105,12 @@ FullSignalK.prototype.addUpdate = function(context, contextPath, update) { } else { console.error("No source in delta update:" + JSON.stringify(update)); } - addValues(context, contextPath, update.source || update['$source'], update.timestamp, update.values); + if ( update.values ) { + addValues(context, contextPath, update.source || update['$source'], update.timestamp, update.values); + } + if ( update.meta ) { + addMetas(context, contextPath, update.source || update['$source'], update.timestamp, update.meta); + } } FullSignalK.prototype.updateDollarSource = function(context, dollarSource, timestamp) { @@ -198,17 +203,13 @@ function addValue(context, contextPath, source, timestamp, pathValue) { if (!previous[pathPart]) { previous[pathPart] = {}; } - if ( i === splitPath.length-1 && typeof previous[pathPart].value === 'undefined' ) { - let meta = signalkSchema.getMetadata(contextPath + '.' + pathValue.path) - if (meta ) { - //ignore properties from keyswithmetadata.json - meta = JSON.parse(JSON.stringify(meta)) - delete meta.properties - + if ( i === splitPath.length-1 && typeof previous[pathPart].value === 'undefined' ) { + let meta = signalkSchema.internalGetMetadata(contextPath + '.' + pathValue.path) + if (meta) { _.assign(meta, previous[pathPart].meta) - previous[pathPart].meta = meta + previous[pathPart].meta = meta } - } + } return previous[pathPart]; }, context); } @@ -267,5 +268,17 @@ function setMessage(leaf, source) { } } +function addMetas(context, contextPath, source, timestamp, metas) { + metas.forEach(metaPathValue => addMeta(context, contextPath, source, timestamp, metaPathValue)) +} + +function addMeta(context, contextPath, source, timestamp, pathValue) { + if (_.isUndefined(pathValue.path) || _.isUndefined(pathValue.value)) { + console.error("Illegal value in delta:" + JSON.stringify(pathValue)); + return; + } + signalkSchema.addMetaData(contextPath, pathValue.path, pathValue.value) +} + module.exports = FullSignalK; diff --git a/src/index.js b/src/index.js index 2ec20bf77..0f068dc57 100644 --- a/src/index.js +++ b/src/index.js @@ -346,7 +346,55 @@ module.exports.getMetadata = function (path) { const result = metadataByRegex.find(entry => entry.regexp.test('/' + path.replace(/\./g, '/')) ) - return result ? result.metadata : undefined + + return result && Object.keys(result.metadata).length > 0 ? result.metadata : undefined +} + +module.exports.internalGetMetadata = function (path) { + const result = metadataByRegex.find(entry => + entry.regexp.test('/' + path.replace(/\./g, '/')) + ) + + let meta = result ? result.metadata : undefined + const parts = path.split('.') + const key = `/${parts[0]}/*/` + parts.slice(2).join('/') + if ( !module.exports.metadata[key] ) { + meta = result ? JSON.parse(JSON.stringify(result.metadata)) : {} + module.exports.metadata[key] = meta + const regexpKey = + '^' + key.replace(/\*/g, '.*').replace(/RegExp/g, '.*') + '$' + metadataByRegex.unshift({ + regexp: new RegExp(regexpKey), + metadata: meta + }) + } + + return meta +} + +module.exports.addMetaData = function(context, path, meta) { + const root = context.split('.')[0] + const key = `/${root}/*/${path.replace(/\./g, '/')}` + let existing = module.exports.metadata[key] + if ( existing ) { + _.merge(existing, meta) + } else { + let regexMeta = module.exports.getMetadata(context + '.' + path) + if ( regexMeta ) { + let newMeta = JSON.parse(JSON.stringify(regexMeta)) + _.merge(newMeta, meta) + meta = newMeta + } + + module.exports.metadata[key] = meta + + const regexpKey = + '^' + key.replace(/\*/g, '.*').replace(/RegExp/g, '.*') + '$' + metadataByRegex.unshift({ + regexp: new RegExp(regexpKey), + metadata: meta + }) + } } module.exports.getAISShipTypeName = function(id) {