diff --git a/datasets/assetData/assetData.json b/datasets/assetData/assetData.json index 03eb639..3c36bd9 100644 --- a/datasets/assetData/assetData.json +++ b/datasets/assetData/assetData.json @@ -83,6 +83,7 @@ { "id": "hidrostal-pump-001", "name": "hidrostal-H05K-S03R", + "units": ["l/s"] }, { diff --git a/datasets/assetData/index.js b/datasets/assetData/index.js new file mode 100644 index 0000000..af0ccda --- /dev/null +++ b/datasets/assetData/index.js @@ -0,0 +1,89 @@ +const fs = require('fs'); +const path = require('path'); + +class AssetCategoryManager { + constructor(relPath = '.') { + this.assetDir = path.resolve(__dirname, relPath); + this.cache = new Map(); + } + + getCategory(softwareType) { + if (!softwareType) { + throw new Error('softwareType is required'); + } + + if (this.cache.has(softwareType)) { + return this.cache.get(softwareType); + } + + const filePath = path.resolve(this.assetDir, `${softwareType}.json`); + if (!fs.existsSync(filePath)) { + throw new Error(`Asset data '${softwareType}' not found in ${this.assetDir}`); + } + + const raw = fs.readFileSync(filePath, 'utf8'); + const parsed = JSON.parse(raw); + this.cache.set(softwareType, parsed); + return parsed; + } + + hasCategory(softwareType) { + const filePath = path.resolve(this.assetDir, `${softwareType}.json`); + return fs.existsSync(filePath); + } + + listCategories({ withMeta = false } = {}) { + const files = fs.readdirSync(this.assetDir, { withFileTypes: true }); + + return files + .filter( + (entry) => + entry.isFile() && + entry.name.endsWith('.json') && + entry.name !== 'index.json' && + entry.name !== 'assetData.json' + ) + .map((entry) => path.basename(entry.name, '.json')) + .map((name) => { + if (!withMeta) { + return name; + } + + const data = this.getCategory(name); + return { + softwareType: data.softwareType || name, + label: data.label || name, + file: `${name}.json` + }; + }); + } + + searchCategories(query) { + const term = (query || '').trim().toLowerCase(); + if (!term) { + return []; + } + + return this.listCategories({ withMeta: true }).filter( + ({ softwareType, label }) => + softwareType.toLowerCase().includes(term) || + label.toLowerCase().includes(term) + ); + } + + clearCache() { + this.cache.clear(); + } +} + +const assetCategoryManager = new AssetCategoryManager(); + +module.exports = { + AssetCategoryManager, + assetCategoryManager, + getCategory: (softwareType) => assetCategoryManager.getCategory(softwareType), + listCategories: (options) => assetCategoryManager.listCategories(options), + searchCategories: (query) => assetCategoryManager.searchCategories(query), + hasCategory: (softwareType) => assetCategoryManager.hasCategory(softwareType), + clearCache: () => assetCategoryManager.clearCache() +}; diff --git a/datasets/assetData/machine.json b/datasets/assetData/machine.json new file mode 100644 index 0000000..04c8563 --- /dev/null +++ b/datasets/assetData/machine.json @@ -0,0 +1,21 @@ +{ + "id": "machine", + "label": "machine", + "softwareType": "machine", + "suppliers": [ + { + "id": "hidrostal", + "name": "Hidrostal", + "types": [ + { + "id": "pump-centrifugal", + "name": "Centrifugal", + "models": [ + { "id": "hidrostal-H05K-S03R", "name": "hidrostal-H05K-S03R", "units": ["l/s","m3/h"] }, + { "id": "hidrostal-C5-D03R-SHN1", "name": "hidrostal-C5-D03R-SHN1", "units": ["l/s"] } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/datasets/assetData/measurement.json b/datasets/assetData/measurement.json new file mode 100644 index 0000000..04e34ad --- /dev/null +++ b/datasets/assetData/measurement.json @@ -0,0 +1,52 @@ +{ + "id": "sensor", + "label": "Sensor", + "softwareType": "measurement", + "suppliers": [ + { + "id": "vega", + "name": "Vega", + "types": [ + { + "id": "temperature", + "name": "Temperature", + "models": [ + { "id": "vega-temp-10", "name": "VegaTemp 10", "units": ["degC", "degF"] }, + { "id": "vega-temp-20", "name": "VegaTemp 20", "units": ["degC", "degF"] } + ] + }, + { + "id": "pressure", + "name": "Pressure", + "models": [ + { "id": "vega-pressure-10", "name": "VegaPressure 10", "units": ["bar", "mbar", "psi"] }, + { "id": "vega-pressure-20", "name": "VegaPressure 20", "units": ["bar", "mbar", "psi"] } + ] + }, + { + "id": "flow", + "name": "Flow", + "models": [ + { "id": "vega-flow-10", "name": "VegaFlow 10", "units": ["m3/h", "gpm", "l/min"] }, + { "id": "vega-flow-20", "name": "VegaFlow 20", "units": ["m3/h", "gpm", "l/min"] } + ] + }, + { + "id": "level", + "name": "Level", + "models": [ + { "id": "vega-level-10", "name": "VegaLevel 10", "units": ["m", "ft", "mm"] }, + { "id": "vega-level-20", "name": "VegaLevel 20", "units": ["m", "ft", "mm"] } + ] + }, + { + "id": "oxygen", + "name": "Quantity (oxygen)", + "models": [ + { "id": "vega-oxy-10", "name": "VegaOxySense 10", "units": ["g/m3", "mol/m3"] } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/datasets/assetData/modelData/ECDV.json b/datasets/assetData/modelData/ECDV.json new file mode 100644 index 0000000..895c38e --- /dev/null +++ b/datasets/assetData/modelData/ECDV.json @@ -0,0 +1,16 @@ +{ + "1.204": { + "125": { + "x": [0,10,20,30,40,50,60,70,80,90,100], + "y": [0,18,50,95,150,216,337,564,882,1398,1870] + }, + "150": { + "x": [0,10,20,30,40,50,60,70,80,90,100], + "y": [0,25,73,138,217,314,490,818,1281,2029,2715] + }, + "400": { + "x": [0,10,20,30,40,50,60,70,80,90,100], + "y": [0,155,443,839,1322,1911,2982,4980,7795,12349,16524] + } + } +} \ No newline at end of file diff --git a/datasets/assetData/modelData/hidrostal-C5-D03R-SHN1.json b/datasets/assetData/modelData/hidrostal-C5-D03R-SHN1.json new file mode 100644 index 0000000..2ea753b --- /dev/null +++ b/datasets/assetData/modelData/hidrostal-C5-D03R-SHN1.json @@ -0,0 +1,838 @@ +{ + "np": { + "400": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5953611390998625, + 1.6935085477165994, + 3.801139124304824, + 7.367829525776738, + 12.081735423116616 + ] + }, + "500": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.8497068236812997, + 3.801139124304824, + 7.367829525776738, + 12.081735423116616 + ] + }, + "600": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.7497197821018213, + 3.801139124304824, + 7.367829525776738, + 12.081735423116616 + ] + }, + "700": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.788320579602724, + 3.9982668237045984, + 7.367829525776738, + 12.081735423116616 + ] + }, + "800": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.7824519364844427, + 3.9885060367793064, + 7.367829525776738, + 12.081735423116616 + ] + }, + "900": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6934482683506376, + 3.9879559558537054, + 7.367829525776738, + 12.081735423116616 + ] + }, + "1000": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6954385513069579, + 4.0743508382926795, + 7.422392692482345, + 12.081735423116616 + ] + }, + "1100": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 4.160745720731654, + 7.596626714476177, + 12.081735423116616 + ] + }, + "1200": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 4.302551231007837, + 7.637247864947884, + 12.081735423116616 + ] + }, + "1300": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 4.37557913990704, + 7.773442147000839, + 12.081735423116616 + ] + }, + "1400": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 4.334434337766139, + 7.940911352646818, + 12.081735423116616 + ] + }, + "1500": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 4.2327206586037995, + 8.005238800611183, + 12.254836577088351 + ] + }, + "1600": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 4.195405588464695, + 7.991827302945298, + 12.423663269044452 + ] + }, + "1700": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 14.255458319309813, + 8.096768422220196, + 12.584668380908582 + ] + }, + "1800": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 31.54620347513727, + 12.637080520201405 + ] + }, + "1900": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 8.148423429611098, + 12.74916725120127 + ] + }, + "2000": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 8.146439484120116, + 12.905178964345618 + ] + }, + "2100": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 8.149576025637684, + 13.006940917309247 + ] + }, + "2200": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 8.126246430368305, + 13.107503837410825 + ] + }, + "2300": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 8.104379361635342, + 13.223235973280122 + ] + }, + "2400": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 8.135190080423746, + 13.36128347785936 + ] + }, + "2500": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 7.981219508598527, + 13.473697427231842 + ] + }, + "2600": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 7.863899404441271, + 13.50303289156837 + ] + }, + "2700": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 7.658860522528131, + 13.485230880073107 + ] + }, + "2800": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 7.44407948309266, + 13.446135725634615 + ] + }, + "2900": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 0.5522732775894703, + 1.6920721090317592, + 3.8742719210788685, + 7.44407948309266, + 13.413693596332184 + ] + } + }, + "nq": { + "400": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 7.6803204433986965, + 25.506609120436963, + 35.4, + 44.4, + 52.5 + ] + }, + "500": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 22.622804921188227, + 35.4, + 44.4, + 52.5 + ] + }, + "600": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 19.966301579194372, + 35.4, + 44.4, + 52.5 + ] + }, + "700": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 17.430763940163832, + 33.79508340848005, + 44.4, + 52.5 + ] + }, + "800": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 14.752921911234477, + 31.71885034449889, + 44.4, + 52.5 + ] + }, + "900": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 11.854693031181021, + 29.923046639543475, + 44.4, + 52.5 + ] + }, + "1000": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.549433913822687, + 26.734189128096668, + 43.96760750800311, + 52.5 + ] + }, + "1100": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 26.26933164936586, + 42.23523193272671, + 52.5 + ] + }, + "1200": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 24.443114637042832, + 40.57167959798151, + 52.5 + ] + }, + "1300": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 22.41596168949836, + 39.04561852479495, + 52.5 + ] + }, + "1400": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 20.276864821170303, + 37.557663261443224, + 52.252852231224054 + ] + }, + "1500": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 18.252772588147742, + 35.9974418607538, + 50.68604059588987 + ] + }, + "1600": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 16.31441663648616, + 34.51170378091407, + 49.20153034100798 + ] + }, + "1700": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 14.255458319309813, + 33.043410795291045, + 47.820213744181245 + ] + }, + "1800": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 31.54620347513727, + 46.51705619739449 + ] + }, + "1900": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 29.986013742375484, + 45.29506741639918 + ] + }, + "2000": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 28.432646044605782, + 44.107822395271945 + ] + }, + "2100": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 26.892634464336055, + 42.758175515158776 + ] + }, + "2200": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 25.270679127870263, + 41.467063889795895 + ] + }, + "2300": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 23.531132157718837, + 40.293041104955826 + ] + }, + "2400": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 21.815645106750623, + 39.03109248860755 + ] + }, + "2500": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 20.34997949463564, + 37.71320701654063 + ] + }, + "2600": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 18.81710568651804, + 36.35563657017404 + ] + }, + "2700": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 17.259072160217805, + 35.02979557646653 + ] + }, + "2800": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 16, + 33.74372254979665 + ] + }, + "2900": { + "x": [ + 0, + 25.510204081632654, + 51.020408163265309, + 76.530612244897952, + 100 + ], + "y": [ + 6.4, + 9.500000000000002, + 12.7, + 16, + 32.54934541379723 + ] + } + } +} diff --git a/datasets/assetData/modelData/hidrostal-H05K-S03R.json b/datasets/assetData/modelData/hidrostal-H05K-S03R.json new file mode 100644 index 0000000..3c381a7 --- /dev/null +++ b/datasets/assetData/modelData/hidrostal-H05K-S03R.json @@ -0,0 +1,1062 @@ +{ + "np": { + "700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 12.962460720759278, + 20.65443723573673, + 31.029351002816465, + 44.58926412111886, + 62.87460150792057 + ] + }, + "800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 13.035157335397209, + 20.74906989186132, + 31.029351002816465, + 44.58926412111886, + 62.87460150792057 + ] + }, + "900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 13.064663380158798, + 20.927197054134297, + 31.107126521989933, + 44.58926412111886, + 62.87460150792057 + ] + }, + "1000": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 13.039271391128953, + 21.08680188366637, + 31.30899920405947, + 44.58926412111886, + 62.87460150792057 + ] + }, + "1100": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 12.940075520572446, + 21.220547481589954, + 31.51468295656385, + 44.621326083982, + 62.87460150792057 + ] + }, + "1200": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 12.784378070157494, + 21.287467135615458, + 31.736145492247378, + 44.833460637148086, + 62.87460150792057 + ] + }, + "1300": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 12.586915243939579, + 21.276682281369446, + 31.930487772749828, + 45.09147841519212, + 62.87460150792057 + ] + }, + "1400": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 12.072531459639976, + 21.236263402754997, + 31.98957228629009, + 45.343639823277805, + 62.948551456696194 + ] + }, + "1500": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 11.498673648884504, + 20.996631954252724, + 31.954252725886462, + 45.54353714625641, + 63.22528016894755 + ] + }, + "1600": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 52.14679487594751, + 20.746724065725342, + 31.960270693111905, + 45.6989826531509, + 63.50000000000001 + ] + }, + "1700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 10.785741081439639, + 20.410520957192535, + 31.950197200275465, + 45.844022293894504, + 63.800401477703126 + ] + }, + "1800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 10.26507140279083, + 20.02134876415971, + 31.90474593035864, + 45.99882821699525, + 64.10190222175436 + ] + }, + "1900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.844493687783078, + 19.615126745440445, + 31.784477814504157, + 46.121518686299474, + 64.37205899496851 + ] + }, + "2000": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.42546845395214, + 19.224613161465353, + 31.3852031134771, + 46.15771544706397, + 64.55065634962911 + ] + }, + "2100": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.977806634186596, + 18.777333452839002, + 31.231492686456505, + 46.13420576468383, + 64.64634734417953 + ] + }, + "2200": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.5551220832516, + 18.192271683023783, + 31.21886730567425, + 46.10526642440768, + 64.7459373335406 + ] + }, + "2300": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.224790390000274, + 17.635073073073073, + 30.69719637959011, + 46.04336860563764, + 64.87880030950727 + ] + }, + "2400": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 17.235714899207412, + 30.206677994537266, + 45.90194286632148, + 65.00133289948793 + ] + }, + "2500": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 16.699519153953943, + 29.81226369335321, + 45.68999350609509, + 65.08194121217663 + ] + }, + "2600": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 16.128295133509337, + 29.372650465392372, + 45.440269896240885, + 65.1262338514688 + ] + }, + "2700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 15.655831107176521, + 28.888887637256676, + 45.14580957087996, + 65.13308230125698 + ] + }, + "2800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 15.218098933011891, + 28.362864023341317, + 44.807426250648106, + 65.10511931024406 + ] + }, + "2900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 14.727036592419225, + 27.800257499369994, + 44.41688206158469, + 65.01783815190142 + ] + }, + "3000": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 14.220778455429796, + 27.231492686456505, + 44.05531409059111, + 64.84454626378002 + ] + }, + "3100": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.791032481569887, + 26.655487058053755, + 43.47550152847766, + 64.61338781598111 + ] + }, + "3200": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 57.998168647814666, + 42.997354839160536, + 64.33911122026377 + ] + }, + "3300": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 53.35067019159144, + 42.48429874246399, + 64.03769740244357 + ] + }, + "3400": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 24.605489108239045, + 41.93544657954916, + 63.75332312922636 + ] + }, + "3500": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 24.02776812223464, + 41.3462311518563, + 63.43861799695663 + ] + }, + "3600": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 23.461492562203443, + 40.66666743038082, + 63.03442493367597 + ] + }, + "3700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 22.83964444901582, + 39.93227924494096, + 62.58510941648396 + ] + }, + "3800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 22.224853190033304, + 39.26854818553173, + 62.120049154943764 + ] + }, + "3900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 8.219999984177646, + 13.426327986363882, + 21.72969647212158, + 38.65394379517984, + 61.64012936635131 + ] + } + }, + "nq": { + "700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 119.13938764447377, + 150.12178608265387, + 178.82698019104356, + 202.3699313222398, + 227.06382297856618 + ] + }, + "800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 112.59072109293984, + 148.15847460389205, + 178.82698019104356, + 202.3699313222398, + 227.06382297856618 + ] + }, + "900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 105.6217241180404, + 144.00502117747064, + 177.15212647335034, + 202.3699313222398, + 227.06382297856618 + ] + }, + "1000": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 97.96933385655602, + 139.33203004341362, + 172.8335214963562, + 202.3699313222398, + 227.06382297856618 + ] + }, + "1100": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 89.46890733013123, + 133.63746503107248, + 168.6757638770697, + 201.51457815731206, + 227.06382297856618 + ] + }, + "1200": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 81.7102176307068, + 127.54746478805862, + 164.86083942366332, + 197.9278536516828, + 227.06382297856618 + ] + }, + "1300": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 73.54434350844221, + 121.17569010344418, + 160.74497886055957, + 194.59764221140935, + 227.06382297856618 + ] + }, + "1400": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 65.44062943901834, + 114.06019126455426, + 155.75252082246928, + 191.17149532208072, + 226.18795889319966 + ] + }, + "1500": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 58.16022827241729, + 106.8304040176964, + 150.34769411635546, + 187.41150790422392, + 223.01071026385065 + ] + }, + "1600": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 52.14679487594751, + 99.83305618056556, + 144.95937497345926, + 183.42837752248894, + 219.8652102448096 + ] + }, + "1700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 46.01552158918748, + 93.03792449348434, + 139.34246720444983, + 179.30356404990695, + 216.85840103402688 + ] + }, + "1800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 39.891102390431755, + 86.36278038299652, + 133.36260934920088, + 175.064220776007, + 213.87502962516638 + ] + }, + "1900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 34.11562677513334, + 79.92122861259746, + 127.3583046971797, + 170.60370417418847, + 210.68808498795732 + ] + }, + "2000": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 28.23139893028536, + 74.27239543161777, + 121.3852031134771, + 165.77656329385528, + 207.11383345844555 + ] + }, + "2100": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 22.028625643397625, + 68.52803664413138, + 115.60209814095579, + 160.766567321836, + 203.25772755139087 + ] + }, + "2200": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 15.99225052287954, + 62.252556641890656, + 109.75606164153551, + 155.8982054779732, + 199.33642607507025 + ] + }, + "2300": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 10.057512077941812, + 56.78739880947559, + 103.28490253306859, + 150.87040317632852, + 195.3712838183181 + ] + }, + "2400": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 51.89879972018922, + 97.49411123502856, + 145.15861930790484, + 191.3102286463588 + ] + }, + "2500": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 46.49650512979005, + 92.5946794216408, + 139.3607940098774, + 187.1228895952043 + ] + }, + "2600": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 40.96259596169048, + 87.48581221097406, + 134.10330733835585, + 182.81452539519677 + ] + }, + "2700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 35.97902929973601, + 82.22524681851449, + 129.0407272627695, + 178.46909993743765 + ] + }, + "2800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 31.23575309746966, + 77.15557437941118, + 124.12760990251361, + 174.10587281860919 + ] + }, + "2900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 26.43435480236642, + 72.24738368847274, + 119.17501218716764, + 169.57138175798616 + ] + }, + "3000": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 21.604008702139296, + 67.42496298247559, + 114.05531409059111, + 164.73832634582294 + ] + }, + "3100": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 16.57058014337364, + 62.68624249227209, + 109.06006424231046, + 159.88207336974 + ] + }, + "3200": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 57.998168647814666, + 104.24541477723719, + 155.19789417429632 + ] + }, + "3300": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 53.35067019159144, + 99.62632764730057, + 150.4942891087851 + ] + }, + "3400": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 48.8526661624979, + 95.33061875213433, + 145.56922638322362 + ] + }, + "3500": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 44.55023162119764, + 91.08960051646183, + 140.69583687494227 + ] + }, + "3600": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 40.31135640023136, + 86.51969834209932, + 136.26067387204347 + ] + }, + "3700": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 36.07819040356928, + 81.84472835862138, + 132.05652400156956 + ] + }, + "3800": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 31.85665211119843, + 77.5230204653733, + 127.71198568555374 + ] + }, + "3900": { + "x": [ + 0, + 24.59, + 49.18, + 73.77, + 100 + ], + "y": [ + 9.542570302282291, + 11.584188419724269, + 27.623838938465713, + 73.46672821834078, + 123.26611832311883 + ] + } + } +} \ No newline at end of file diff --git a/datasets/assetData/modelData/index.js b/datasets/assetData/modelData/index.js new file mode 100644 index 0000000..c4af256 --- /dev/null +++ b/datasets/assetData/modelData/index.js @@ -0,0 +1,124 @@ +const fs = require('fs'); +const path = require('path'); + +class AssetLoader { + constructor() { + this.relPath = './' + this.baseDir = path.resolve(__dirname, this.relPath); + this.cache = new Map(); // Cache loaded JSON files for better performance + } + + /** + * Load a specific curve by type + * @param {string} curveType - The curve identifier (e.g., 'hidrostal-H05K-S03R') + * @returns {Object|null} The curve data object or null if not found + */ + loadModel(modelType) { + return this.loadAsset('models', modelType); + } + + /** + * Load any asset from a specific dataset folder + * @param {string} datasetType - The dataset folder name (e.g., 'curves', 'assetData') + * @param {string} assetId - The specific asset identifier + * @returns {Object|null} The asset data object or null if not found + */ + loadAsset(datasetType, assetId) { + //const cacheKey = `${datasetType}/${assetId}`; + const cacheKey = `${assetId}`; + + + // Check cache first + if (this.cache.has(cacheKey)) { + return this.cache.get(cacheKey); + } + + try { + const filePath = path.join(this.baseDir, `${assetId}.json`); + + // Check if file exists + if (!fs.existsSync(filePath)) { + console.warn(`Asset not found: ${filePath}`); + return null; + } + + // Load and parse JSON + const rawData = fs.readFileSync(filePath, 'utf8'); + const assetData = JSON.parse(rawData); + + // Cache the result + this.cache.set(cacheKey, assetData); + + return assetData; + } catch (error) { + console.error(`Error loading asset ${cacheKey}:`, error.message); + return null; + } + } + + /** + * Get all available assets in a dataset + * @param {string} datasetType - The dataset folder name + * @returns {string[]} Array of available asset IDs + */ + getAvailableAssets(datasetType) { + try { + const datasetPath = path.join(this.baseDir, datasetType); + + if (!fs.existsSync(datasetPath)) { + return []; + } + + return fs.readdirSync(datasetPath) + .filter(file => file.endsWith('.json')) + .map(file => file.replace('.json', '')); + } catch (error) { + console.error(`Error reading dataset ${datasetType}:`, error.message); + return []; + } + } + + /** + * Clear the cache (useful for development/testing) + */ + clearCache() { + this.cache.clear(); + } +} + +// Create and export a singleton instance +const assetLoader = new AssetLoader(); + +module.exports = { + AssetLoader, + assetLoader, + // Convenience methods for backward compatibility + loadModel: (modelType) => assetLoader.loadModel(modelType), + loadAsset: (datasetType, assetId) => assetLoader.loadAsset(datasetType, assetId), + getAvailableAssets: (datasetType) => assetLoader.getAvailableAssets(datasetType) +}; + +/* +// Example usage in your scripts +const loader = new AssetLoader(); + +// Load a specific curve +const curve = loader.loadModel('hidrostal-H05K-S03R'); +if (curve) { + console.log('Model loaded:', curve); +} else { + console.log('Model not found'); +} +/* +// Load any asset from any dataset +const someAsset = loadAsset('assetData', 'some-asset-id'); + +// Get list of available models +const availableCurves = getAvailableAssets('curves'); +console.log('Available curves:', availableCurves); + +// Using the class directly for more control +const { AssetLoader } = require('./index.js'); +const customLoader = new AssetLoader(); +const data = customLoader.loadCurve('hidrostal-H05K-S03R'); +*/ \ No newline at end of file diff --git a/datasets/assetData/valve.json b/datasets/assetData/valve.json new file mode 100644 index 0000000..56ba2e1 --- /dev/null +++ b/datasets/assetData/valve.json @@ -0,0 +1,27 @@ +{ + "id": "valve", + "label": "valve", + "softwareType": "valve", + "suppliers": [ + { + "id": "binder", + "name": "Binder Engineering", + "types": [ + { + "id": "valve-gate", + "name": "Gate", + "models": [ + { "id": "binder-valve-001", "name": "ECDV", "units": ["m3/h", "gpm", "l/min"] } + ] + }, + { + "id": "valve-jet", + "name": "Jet", + "models": [ + { "id": "binder-valve-002", "name": "JCV", "units": ["m3/h", "gpm", "l/min"] } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/datasets/tagcodeapp_assets.json b/datasets/tagcodeapp_assets.json index ec2d0b9..fb45e9d 100644 --- a/datasets/tagcodeapp_assets.json +++ b/datasets/tagcodeapp_assets.json @@ -1 +1,1362 @@ -{"success":true,"data":[{"asset_id":"1","profile_id":"0","asset_tag_number":"L001","asset_name":"Test laptop R&D","asset_description":"Test voor een laptop voor R&D","asset_date_created":"2025-01-16 14:19:32","asset_status":"actief ","product_model_id":"1","location_id":"1","product_model_uuid":"0123456789","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":null,"process_name":"Voorbezinking"},{"asset_id":"2","profile_id":"1","asset_tag_number":"L9764","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-01-18 19:03:15","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"3","profile_id":"1","asset_tag_number":"L6616","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-01-18 19:03:47","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"4","profile_id":"1","asset_tag_number":"L4972","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-01-18 19:05:18","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"0","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"5","profile_id":"1","asset_tag_number":"L3586","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-01-18 19:05:48","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"1234567890","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"6","profile_id":"1","asset_tag_number":"L6719","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-01-18 19:06:38","asset_status":"inactief","product_model_id":"2","location_id":"1","product_model_uuid":"12357890","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 13","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"7","profile_id":"1","asset_tag_number":"P6565","asset_name":"sensor","asset_description":"Computer","asset_date_created":"2025-02-03 08:50:24","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"52","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"8","profile_id":"1","asset_tag_number":"P9573","asset_name":"sensor","asset_description":"Test3","asset_date_created":"2025-02-03 08:56:57","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"9","profile_id":"1","asset_tag_number":"P8081","asset_name":"sensor","asset_description":"Test4","asset_date_created":"2025-02-03 08:58:52","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"10","profile_id":"1","asset_tag_number":"P3179","asset_name":"sensor","asset_description":"Pressure Transmitter 1","asset_date_created":"2025-02-03 09:08:37","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"11","profile_id":"1","asset_tag_number":"P7975","asset_name":"sensor","asset_description":"PT99","asset_date_created":"2025-02-03 10:12:48","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"12","profile_id":"1","asset_tag_number":"P7871","asset_name":"sensor","asset_description":"PT99","asset_date_created":"2025-02-03 10:50:39","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"13","profile_id":"1","asset_tag_number":"P9288","asset_name":"sensor","asset_description":"PT99","asset_date_created":"2025-02-03 10:50:43","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"14","profile_id":"1","asset_tag_number":"19468","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 14:12:12","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"15","profile_id":"1","asset_tag_number":"18804","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 14:13:54","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"16","profile_id":"1","asset_tag_number":"11795","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 14:13:55","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"17","profile_id":"1","asset_tag_number":"16230","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 14:14:37","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"18","profile_id":"1","asset_tag_number":"14600","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 14:14:38","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"19","profile_id":"1","asset_tag_number":"16535","asset_name":"AssetNaam2","asset_description":"Beschrijving","asset_date_created":"2025-02-13 14:14:52","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123453789","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"20","profile_id":"1","asset_tag_number":"61894","asset_name":"sensor","asset_description":"PT1","asset_date_created":"2025-02-13 15:26:47","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"21","profile_id":"1","asset_tag_number":"62803","asset_name":"sensor","asset_description":"PT999","asset_date_created":"2025-02-13 15:27:06","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"22","profile_id":"1","asset_tag_number":"63753","asset_name":"sensor","asset_description":"PT999","asset_date_created":"2025-02-13 15:27:32","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"23","profile_id":"1","asset_tag_number":"undefined","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 15:46:59","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"24","profile_id":"1","asset_tag_number":"null","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 15:49:03","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"26","profile_id":"1","asset_tag_number":"19134","asset_name":"AssetNaam","asset_description":"Beschrijving","asset_date_created":"2025-02-13 15:50:36","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"27","profile_id":"1","asset_tag_number":"63247","asset_name":"sensor","asset_description":"PT1","asset_date_created":"2025-02-13 15:52:43","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"28","profile_id":"1","asset_tag_number":"62149","asset_name":"sensor","asset_description":"PT2","asset_date_created":"2025-02-13 15:52:53","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"29","profile_id":"1","asset_tag_number":"61688","asset_name":"sensor","asset_description":"PT1","asset_date_created":"2025-02-13 15:56:50","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"30","profile_id":"1","asset_tag_number":"62927","asset_name":"sensor","asset_description":"PT1","asset_date_created":"2025-02-13 16:02:12","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"31","profile_id":"1","asset_tag_number":"66465","asset_name":"sensor","asset_description":"PT1","asset_date_created":"2025-02-13 16:02:29","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"32","profile_id":"1","asset_tag_number":"65180","asset_name":"sensor","asset_description":"PT1","asset_date_created":"2025-02-13 16:05:07","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":"Voorbezinking"},{"asset_id":"33","profile_id":"1","asset_tag_number":"65992","asset_name":"AssetNaamtest","asset_description":"Beschrijving","asset_date_created":"2025-02-13 16:05:18","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"34","profile_id":"1","asset_tag_number":"67315","asset_name":"AssetNaamtest","asset_description":"Beschrijving","asset_date_created":"2025-02-13 16:09:42","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"35","profile_id":"1","asset_tag_number":"18140","asset_name":"AssetNaamtest","asset_description":"Beschrijving","asset_date_created":"2025-02-13 16:22:37","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"36","profile_id":"1","asset_tag_number":"L000035","asset_name":"AssetNaamtest","asset_description":"Beschrijving","asset_date_created":"2025-02-13 16:22:57","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"37","profile_id":"1","asset_tag_number":"L000036","asset_name":"AssetNaamtest","asset_description":"Beschrijving","asset_date_created":"2025-02-13 16:31:26","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"123456789","process_id":"11","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":null},{"asset_id":"38","profile_id":"1","asset_tag_number":"P000037","asset_name":"sensor","asset_description":"testasdf","asset_date_created":"2025-02-13 16:47:33","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"39","profile_id":"1","asset_tag_number":"P000038","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 13:12:36","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"40","profile_id":"1","asset_tag_number":"P000039","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 13:13:17","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"41","profile_id":"1","asset_tag_number":"P000040","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 13:15:26","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"42","profile_id":"1","asset_tag_number":"P000041","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 13:22:02","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"43","profile_id":"1","asset_tag_number":"D000042","asset_name":"test","asset_description":"test","asset_date_created":"2025-02-20 13:35:30","asset_status":"inactief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"44","profile_id":"1","asset_tag_number":"D000043","asset_name":"gdxg","asset_description":"dssdsdsd","asset_date_created":"2025-02-20 13:36:50","asset_status":"inactief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"45","profile_id":"1","asset_tag_number":"P000044","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 14:06:53","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"46","profile_id":"1","asset_tag_number":"P000045","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:06:34","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"47","profile_id":"1","asset_tag_number":"P000046","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:23:00","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"48","profile_id":"1","asset_tag_number":"P000047","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:23:05","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"49","profile_id":"1","asset_tag_number":"P000048","asset_name":"pump","asset_description":"m2","asset_date_created":"2025-02-20 15:24:47","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"50","profile_id":"1","asset_tag_number":"P000049","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:24:55","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"51","profile_id":"1","asset_tag_number":"P000050","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:27:36","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"2147483647","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"52","profile_id":"1","asset_tag_number":"P000051","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:29:41","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"53","profile_id":"1","asset_tag_number":"P000052","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:30:53","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"54","profile_id":"1","asset_tag_number":"P000053","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:31:48","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"2147483647","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"55","profile_id":"1","asset_tag_number":"P000054","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:36:19","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"2147483647","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"56","profile_id":"1","asset_tag_number":"P000055","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:42:37","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"2147483647","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"57","profile_id":"1","asset_tag_number":"P000056","asset_name":"pump","asset_description":"m2","asset_date_created":"2025-02-20 15:43:46","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"2147483647","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"58","profile_id":"1","asset_tag_number":"P000057","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:46:10","asset_status":"actief","product_model_id":null,"location_id":null,"product_model_uuid":null,"process_id":null,"location_latitude":null,"location_longitude":null,"location_name":null,"location_description":null,"location_address":null,"product_model_name":null,"product_model_description":null,"product_subtype_name":null,"profile_name":"Watersystemen","process_name":null},{"asset_id":"59","profile_id":"1","asset_tag_number":"P000058","asset_name":"pump","asset_description":"m1","asset_date_created":"2025-02-20 15:46:38","asset_status":"actief","product_model_id":"6","location_id":"1","product_model_uuid":"123456789","process_id":"2147483647","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Vegabar 14","product_model_description":"vegabar 14","product_subtype_name":"pressure","profile_name":"Watersystemen","process_name":null},{"asset_id":"60","profile_id":"1","asset_tag_number":"P000059","asset_name":"sensor","asset_description":"PT110","asset_date_created":"2025-02-25 15:25:01","asset_status":"actief","product_model_id":"1","location_id":"1","product_model_uuid":"b02b3a50-3f36-4ab0-9479-84de2fca9cb1","process_id":"1","location_latitude":"51.6314","location_longitude":"4.708","location_name":"RWZI Nieuwveer","location_description":null,"location_address":null,"product_model_name":"Macbook Air 12","product_model_description":null,"product_subtype_name":"Laptop","profile_name":"Watersystemen","process_name":"Voorbezinking"}]} \ No newline at end of file +{ + "success": true, + "data": [ + { + "asset_id": "1", + "profile_id": "0", + "asset_tag_number": "L001", + "asset_name": "Test laptop R&D", + "asset_description": "Test voor een laptop voor R&D", + "asset_date_created": "2025-01-16 14:19:32", + "asset_status": "actief ", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "0123456789", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": null, + "process_name": "Voorbezinking" + }, + { + "asset_id": "2", + "profile_id": "1", + "asset_tag_number": "L9764", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-01-18 19:03:15", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "3", + "profile_id": "1", + "asset_tag_number": "L6616", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-01-18 19:03:47", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "4", + "profile_id": "1", + "asset_tag_number": "L4972", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-01-18 19:05:18", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "0", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "5", + "profile_id": "1", + "asset_tag_number": "L3586", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-01-18 19:05:48", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "1234567890", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "6", + "profile_id": "1", + "asset_tag_number": "L6719", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-01-18 19:06:38", + "asset_status": "inactief", + "product_model_id": "2", + "location_id": "1", + "product_model_uuid": "12357890", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 13", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "7", + "profile_id": "1", + "asset_tag_number": "P6565", + "asset_name": "sensor", + "asset_description": "Computer", + "asset_date_created": "2025-02-03 08:50:24", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "52", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "8", + "profile_id": "1", + "asset_tag_number": "P9573", + "asset_name": "sensor", + "asset_description": "Test3", + "asset_date_created": "2025-02-03 08:56:57", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "9", + "profile_id": "1", + "asset_tag_number": "P8081", + "asset_name": "sensor", + "asset_description": "Test4", + "asset_date_created": "2025-02-03 08:58:52", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "10", + "profile_id": "1", + "asset_tag_number": "P3179", + "asset_name": "sensor", + "asset_description": "Pressure Transmitter 1", + "asset_date_created": "2025-02-03 09:08:37", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "11", + "profile_id": "1", + "asset_tag_number": "P7975", + "asset_name": "sensor", + "asset_description": "PT99", + "asset_date_created": "2025-02-03 10:12:48", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "12", + "profile_id": "1", + "asset_tag_number": "P7871", + "asset_name": "sensor", + "asset_description": "PT99", + "asset_date_created": "2025-02-03 10:50:39", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "13", + "profile_id": "1", + "asset_tag_number": "P9288", + "asset_name": "sensor", + "asset_description": "PT99", + "asset_date_created": "2025-02-03 10:50:43", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "14", + "profile_id": "1", + "asset_tag_number": "19468", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 14:12:12", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "15", + "profile_id": "1", + "asset_tag_number": "18804", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 14:13:54", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "16", + "profile_id": "1", + "asset_tag_number": "11795", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 14:13:55", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "17", + "profile_id": "1", + "asset_tag_number": "16230", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 14:14:37", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "18", + "profile_id": "1", + "asset_tag_number": "14600", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 14:14:38", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "19", + "profile_id": "1", + "asset_tag_number": "16535", + "asset_name": "AssetNaam2", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 14:14:52", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123453789", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "20", + "profile_id": "1", + "asset_tag_number": "61894", + "asset_name": "sensor", + "asset_description": "PT1", + "asset_date_created": "2025-02-13 15:26:47", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "21", + "profile_id": "1", + "asset_tag_number": "62803", + "asset_name": "sensor", + "asset_description": "PT999", + "asset_date_created": "2025-02-13 15:27:06", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "22", + "profile_id": "1", + "asset_tag_number": "63753", + "asset_name": "sensor", + "asset_description": "PT999", + "asset_date_created": "2025-02-13 15:27:32", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "23", + "profile_id": "1", + "asset_tag_number": "undefined", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 15:46:59", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "24", + "profile_id": "1", + "asset_tag_number": "null", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 15:49:03", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "26", + "profile_id": "1", + "asset_tag_number": "19134", + "asset_name": "AssetNaam", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 15:50:36", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "27", + "profile_id": "1", + "asset_tag_number": "63247", + "asset_name": "sensor", + "asset_description": "PT1", + "asset_date_created": "2025-02-13 15:52:43", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "28", + "profile_id": "1", + "asset_tag_number": "62149", + "asset_name": "sensor", + "asset_description": "PT2", + "asset_date_created": "2025-02-13 15:52:53", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "29", + "profile_id": "1", + "asset_tag_number": "61688", + "asset_name": "sensor", + "asset_description": "PT1", + "asset_date_created": "2025-02-13 15:56:50", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "30", + "profile_id": "1", + "asset_tag_number": "62927", + "asset_name": "sensor", + "asset_description": "PT1", + "asset_date_created": "2025-02-13 16:02:12", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "31", + "profile_id": "1", + "asset_tag_number": "66465", + "asset_name": "sensor", + "asset_description": "PT1", + "asset_date_created": "2025-02-13 16:02:29", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "32", + "profile_id": "1", + "asset_tag_number": "65180", + "asset_name": "sensor", + "asset_description": "PT1", + "asset_date_created": "2025-02-13 16:05:07", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + }, + { + "asset_id": "33", + "profile_id": "1", + "asset_tag_number": "65992", + "asset_name": "AssetNaamtest", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 16:05:18", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "34", + "profile_id": "1", + "asset_tag_number": "67315", + "asset_name": "AssetNaamtest", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 16:09:42", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "35", + "profile_id": "1", + "asset_tag_number": "18140", + "asset_name": "AssetNaamtest", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 16:22:37", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "36", + "profile_id": "1", + "asset_tag_number": "L000035", + "asset_name": "AssetNaamtest", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 16:22:57", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "37", + "profile_id": "1", + "asset_tag_number": "L000036", + "asset_name": "AssetNaamtest", + "asset_description": "Beschrijving", + "asset_date_created": "2025-02-13 16:31:26", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "11", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "38", + "profile_id": "1", + "asset_tag_number": "P000037", + "asset_name": "sensor", + "asset_description": "testasdf", + "asset_date_created": "2025-02-13 16:47:33", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "39", + "profile_id": "1", + "asset_tag_number": "P000038", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 13:12:36", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "40", + "profile_id": "1", + "asset_tag_number": "P000039", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 13:13:17", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "41", + "profile_id": "1", + "asset_tag_number": "P000040", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 13:15:26", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "42", + "profile_id": "1", + "asset_tag_number": "P000041", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 13:22:02", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "43", + "profile_id": "1", + "asset_tag_number": "D000042", + "asset_name": "test", + "asset_description": "test", + "asset_date_created": "2025-02-20 13:35:30", + "asset_status": "inactief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "44", + "profile_id": "1", + "asset_tag_number": "D000043", + "asset_name": "gdxg", + "asset_description": "dssdsdsd", + "asset_date_created": "2025-02-20 13:36:50", + "asset_status": "inactief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "45", + "profile_id": "1", + "asset_tag_number": "P000044", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 14:06:53", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "46", + "profile_id": "1", + "asset_tag_number": "P000045", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:06:34", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "47", + "profile_id": "1", + "asset_tag_number": "P000046", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:23:00", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "48", + "profile_id": "1", + "asset_tag_number": "P000047", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:23:05", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "49", + "profile_id": "1", + "asset_tag_number": "P000048", + "asset_name": "pump", + "asset_description": "m2", + "asset_date_created": "2025-02-20 15:24:47", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "50", + "profile_id": "1", + "asset_tag_number": "P000049", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:24:55", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "51", + "profile_id": "1", + "asset_tag_number": "P000050", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:27:36", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "2147483647", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "52", + "profile_id": "1", + "asset_tag_number": "P000051", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:29:41", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "53", + "profile_id": "1", + "asset_tag_number": "P000052", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:30:53", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "54", + "profile_id": "1", + "asset_tag_number": "P000053", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:31:48", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "2147483647", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "55", + "profile_id": "1", + "asset_tag_number": "P000054", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:36:19", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "2147483647", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "56", + "profile_id": "1", + "asset_tag_number": "P000055", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:42:37", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "2147483647", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "57", + "profile_id": "1", + "asset_tag_number": "P000056", + "asset_name": "pump", + "asset_description": "m2", + "asset_date_created": "2025-02-20 15:43:46", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "2147483647", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "58", + "profile_id": "1", + "asset_tag_number": "P000057", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:46:10", + "asset_status": "actief", + "product_model_id": null, + "location_id": null, + "product_model_uuid": null, + "process_id": null, + "location_latitude": null, + "location_longitude": null, + "location_name": null, + "location_description": null, + "location_address": null, + "product_model_name": null, + "product_model_description": null, + "product_subtype_name": null, + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "59", + "profile_id": "1", + "asset_tag_number": "P000058", + "asset_name": "pump", + "asset_description": "m1", + "asset_date_created": "2025-02-20 15:46:38", + "asset_status": "actief", + "product_model_id": "6", + "location_id": "1", + "product_model_uuid": "123456789", + "process_id": "2147483647", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Vegabar 14", + "product_model_description": "vegabar 14", + "product_subtype_name": "pressure", + "profile_name": "Watersystemen", + "process_name": null + }, + { + "asset_id": "60", + "profile_id": "1", + "asset_tag_number": "P000059", + "asset_name": "sensor", + "asset_description": "PT110", + "asset_date_created": "2025-02-25 15:25:01", + "asset_status": "actief", + "product_model_id": "1", + "location_id": "1", + "product_model_uuid": "b02b3a50-3f36-4ab0-9479-84de2fca9cb1", + "process_id": "1", + "location_latitude": "51.6314", + "location_longitude": "4.708", + "location_name": "RWZI Nieuwveer", + "location_description": null, + "location_address": null, + "product_model_name": "Macbook Air 12", + "product_model_description": null, + "product_subtype_name": "Laptop", + "profile_name": "Watersystemen", + "process_name": "Voorbezinking" + } + ] +} \ No newline at end of file diff --git a/index.js b/index.js index 0c437c8..97dffa3 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,7 @@ const validation = require('./src/helper/validationUtils.js'); const configUtils = require('./src/helper/configUtils.js'); const assertions = require('./src/helper/assertionUtils.js') const coolprop = require('./src/coolprop-node/src/index.js'); +const gravity = require('./src/helper/gravity.js') // Domain-specific modules const { MeasurementContainer } = require('./src/measurements/index.js'); @@ -25,7 +26,8 @@ const MenuManager = require('./src/menu/index.js'); const predict = require('./src/predict/predict_class.js'); const interpolation = require('./src/predict/interpolation.js'); const childRegistrationUtils = require('./src/helper/childRegistrationUtils.js'); -const { loadCurve } = require('./datasets/assetData/curves/index.js'); +const { loadCurve } = require('./datasets/assetData/curves/index.js'); //deprecated replace with load model data +const { loadModel } = require('./datasets/assetData/modelData/index.js'); // Export everything module.exports = { @@ -44,5 +46,7 @@ module.exports = { convert, MenuManager, childRegistrationUtils, - loadCurve + loadCurve, //deprecated replace with loadModel + loadModel, + gravity }; diff --git a/src/configs/index.js b/src/configs/index.js index ff85a92..72e867f 100644 --- a/src/configs/index.js +++ b/src/configs/index.js @@ -47,30 +47,30 @@ class ConfigManager { return fs.existsSync(configPath); } - createEndpoint(nodeName) { - try { - // Load the config for this node - const config = this.getConfig(nodeName); - - // Convert config to JSON - const configJSON = JSON.stringify(config, null, 2); + createEndpoint(nodeName) { + try { + // Load the config for this node + const config = this.getConfig(nodeName); - // Assemble the complete script - return ` - // Create the namespace structure - window.EVOLV = window.EVOLV || {}; - window.EVOLV.nodes = window.EVOLV.nodes || {}; - window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {}; + // Convert config to JSON + const configJSON = JSON.stringify(config, null, 2); - // Inject the pre-loaded config data directly into the namespace - window.EVOLV.nodes.${nodeName}.config = ${configJSON}; + // Assemble the complete script + return ` + // Create the namespace structure + window.EVOLV = window.EVOLV || {}; + window.EVOLV.nodes = window.EVOLV.nodes || {}; + window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {}; - console.log('${nodeName} config loaded and endpoint created'); - `; - } catch (error) { - throw new Error(`Failed to create endpoint for '${nodeName}': ${error.message}`); - } + // Inject the pre-loaded config data directly into the namespace + window.EVOLV.nodes.${nodeName}.config = ${configJSON}; + + console.log('${nodeName} config loaded and endpoint created'); + `; + } catch (error) { + throw new Error(`Failed to create endpoint for '${nodeName}': ${error.message}`); } + } } module.exports = ConfigManager; \ No newline at end of file diff --git a/src/configs/pumpingStation.json b/src/configs/pumpingStation.json index d6a0668..5adf4a0 100644 --- a/src/configs/pumpingStation.json +++ b/src/configs/pumpingStation.json @@ -299,6 +299,23 @@ "description": "Reference height to use to identify the height vs other basins with. This will say something more about the expected pressure loss in m head" } }, + "minHeightBasedOn": { + "default": "outlet", + "rules": { + "type": "enum", + "values": [ + { + "value": "inlet", + "description": "Minimum height is based on inlet elevation." + }, + { + "value": "outlet", + "description": "Minimum height is based on outlet elevation." + } + ], + "description": "Basis for minimum height check: inlet or outlet." + } + }, "staticHead": { "default": 12, "rules": { @@ -348,13 +365,13 @@ } }, "control": { - "controlStrategy": { - "default": "levelBased", + "mode": { + "default": "levelbased", "rules": { - "type": "enum", + "type": "string", "values": [ { - "value": "levelBased", + "value": "levelbased", "description": "Lead and lag pumps are controlled by basin level thresholds." }, { @@ -362,9 +379,21 @@ "description": "Pumps target a discharge pressure setpoint." }, { - "value": "flowTracking", + "value": "flowBased", "description": "Pumps modulate to match measured inflow or downstream demand." }, + { + "value": "percentageBased", + "description": "Pumps operate to maintain basin volume at a target percentage." + }, + { + "value":"powerBased", + "description": "Pumps are controlled based on power consumption.For example, to limit peak power usage or operate within netcongestion limits." + }, + { + "value": "hybrid", + "description": "Combines multiple control strategies for optimized operation." + }, { "value": "manual", "description": "Pumps are operated manually or by an external controller." @@ -373,94 +402,112 @@ "description": "Primary control philosophy for pump actuation." } }, - "levelSetpoints": { - "default": { - "startLeadPump": 1.2, - "stopLeadPump": 0.8, - "startLagPump": 1.8, - "stopLagPump": 1.4, - "alarmHigh": 2.3, - "alarmLow": 0.3 - }, + "allowedModes": { + "default": [ + "levelbased", + "pressurebased", + "flowbased", + "percentagebased", + "powerbased", + "manual" + ], "rules": { - "type": "object", - "description": "Level thresholds that govern pump staging and alarms (m).", - "schema": { - "startLeadPump": { - "default": 1.2, - "rules": { - "type": "number", - "description": "Level that starts the lead pump." - } - }, - "stopLeadPump": { - "default": 0.8, - "rules": { - "type": "number", - "description": "Level that stops the lead pump." - } - }, - "startLagPump": { - "default": 1.8, - "rules": { - "type": "number", - "description": "Level that starts the lag pump." - } - }, - "stopLagPump": { - "default": 1.4, - "rules": { - "type": "number", - "description": "Level that stops the lag pump." - } - }, - "alarmHigh": { - "default": 2.3, - "rules": { - "type": "number", - "description": "High level alarm threshold." - } - }, - "alarmLow": { - "default": 0.3, - "rules": { - "type": "number", - "description": "Low level alarm threshold." - } - } + "type": "set", + "itemType": "string", + "description": "List of control modes that the station is permitted to operate in." + } + }, + "levelbased": { + "thresholds": { + "default": [30,40,50,60,70,80,90], + "rules": { + "type": "array", + "description": "Each time a threshold is overwritten a new pump can start or kick into higher gear. Volume thresholds (%) in ascending order used for level-based control." + } + }, + "timeThresholdSeconds": { + "default": 5, + "rules": { + "type": "number", + "min": 0, + "description": "Duration the volume condition must persist before triggering pump actions (seconds)." } } }, - "pressureSetpoint": { - "default": 250, - "rules": { - "type": "number", - "min": 0, - "description": "Target discharge pressure when operating in pressure control (kPa)." + "pressureBased": { + "pressureSetpoint": { + "default": 1000, + "rules": { + "type": "number", + "min": 0, + "max": 5000, + "description": "Target discharge pressure when operating in pressure control (kPa)." + } } }, - "alarmDebounceSeconds": { - "default": 10, - "rules": { - "type": "number", - "min": 0, - "description": "Time a condition must persist before raising an alarm (seconds)." + "flowBased": { + "equalizationTargetPercent": { + "default": 60, + "rules": { + "type": "number", + "min": 0, + "max": 100, + "description": "Target fill percentage of the basin when operating in equalization mode." + } + }, + "flowBalanceTolerance": { + "default": 5, + "rules": { + "type": "number", + "min": 0, + "description": "Allowable error between inflow and outflow before adjustments are triggered (m3/h)." + } } }, - "equalizationTargetPercent": { - "default": 60, - "rules": { - "type": "number", - "min": 0, - "max": 100, - "description": "Target fill percentage of the basin when operating in equalization mode." + "percentageBased": { + "targetVolumePercent": { + "default": 50, + "rules": { + "type": "number", + "min": 0, + "max": 100, + "description": "Target basin volume percentage to maintain during percentage-based control." + } + }, + "tolerancePercent": { + "default": 5, + "rules": { + "type": "number", + "min": 0, + "description": "Acceptable deviation from the target volume percentage before corrective action is taken." + } } }, - "autoRestartAfterPowerLoss": { - "default": true, - "rules": { - "type": "boolean", - "description": "If true, pumps resume based on last known state after power restoration." + "powerBased": { + "maxPowerKW": { + "default": 50, + "rules": { + "type": "number", + "min": 0, + "description": "Maximum allowable power consumption for the pumping station (kW)." + } + }, + "powerControlMode": { + "default": "limit", + "rules": { + "type": "enum", + "values": [ + { + "value": "limit", + "description": "Limit pump operation to stay below the max power threshold." + }, + { + "value": "optimize", + "description": "Optimize pump scheduling to minimize power usage while meeting flow demands." + } + ], + "description": "Defines how power constraints are managed during operation." + } } }, "manualOverrideTimeoutMinutes": { @@ -470,13 +517,63 @@ "min": 0, "description": "Duration after which a manual override expires automatically (minutes)." } + } + }, + "safety": { + "enableDryRunProtection": { + "default": true, + "rules": { + "type": "boolean", + "description": "If true, pumps will be prevented from running if basin volume is too low." + } }, - "flowBalanceTolerance": { - "default": 5, + "dryRunThresholdPercent": { + "default": 2, "rules": { "type": "number", "min": 0, - "description": "Allowable error between inflow and outflow before adjustments are triggered (m3/h)." + "max": 100, + "description": "Volume percentage below which dry run protection activates." + } + }, + "dryRunDebounceSeconds": { + "default": 30, + "rules": { + "type": "number", + "min": 0, + "description": "Time the low-volume condition must persist before dry-run protection engages (seconds)." + } + }, + "enableOverfillProtection": { + "default": true, + "rules": { + "type": "boolean", + "description": "If true, high level alarms and shutdowns will be enforced to prevent overfilling." + } + }, + "overfillThresholdPercent": { + "default": 98, + "rules": { + "type": "number", + "min": 0, + "max": 100, + "description": "Volume percentage above which overfill protection activates." + } + }, + "overfillDebounceSeconds": { + "default": 30, + "rules": { + "type": "number", + "min": 0, + "description": "Time the high-volume condition must persist before overfill protection engages (seconds)." + } + }, + "timeleftToFullOrEmptyThresholdSeconds": { + "default": 120, + "rules": { + "type": "number", + "min": 0, + "description": "Time threshold (seconds) used to predict imminent full or empty conditions." } } }, diff --git a/src/configs/rotatingMachine.json b/src/configs/rotatingMachine.json index 2c83be7..102a0b3 100644 --- a/src/configs/rotatingMachine.json +++ b/src/configs/rotatingMachine.json @@ -245,10 +245,6 @@ { "value": "fysicalControl", "description": "Controlled via physical buttons or switches; ignores external automated commands." - }, - { - "value": "maintenance", - "description": "No active control from auto, virtual, or fysical sources." } ], "description": "The operational mode of the machine." @@ -260,7 +256,14 @@ "type": "object", "schema":{ "auto": { - "default": ["statusCheck", "execMovement", "execSequence", "emergencyStop"], + "default": [ + "statuscheck", + "execmovement", + "execsequence", + "flowmovement", + "emergencystop", + "entermaintenance" + ], "rules": { "type": "set", "itemType": "string", @@ -268,7 +271,14 @@ } }, "virtualControl": { - "default": ["statusCheck", "execMovement", "execSequence", "emergencyStop"], + "default": [ + "statuscheck", + "execmovement", + "flowmovement", + "execsequence", + "emergencystop", + "exitmaintenance" + ], "rules": { "type": "set", "itemType": "string", @@ -276,25 +286,22 @@ } }, "fysicalControl": { - "default": ["statusCheck", "emergencyStop"], + "default": [ + "statuscheck", + "emergencystop", + "entermaintenance", + "exitmaintenance" + ], "rules": { "type": "set", "itemType": "string", "description": "Actions allowed in fysicalControl mode." } - }, - "maintenance": { - "default": ["statusCheck"], - "rules": { - "type": "set", - "itemType": "string", - "description": "Actions allowed in maintenance mode." - } + } } }, "description": "Information about valid command sources recognized by the machine." - } - }, + }, "allowedSources":{ "default": {}, "rules": { @@ -386,6 +393,22 @@ "itemType": "string", "description": "Sequence of states for booting up the machine." } + }, + "entermaintenance":{ + "default": ["stopping","coolingdown","idle","maintenance"], + "rules": { + "type": "set", + "itemType": "string", + "description": "Sequence of states if the machine is running to put it in maintenance state" + } + }, + "exitmaintenance":{ + "default": ["off","idle"], + "rules": { + "type": "set", + "itemType": "string", + "description": "Sequence of states if the machine is running to put it in maintenance state" + } } } }, diff --git a/src/coolprop-node/src/index.js b/src/coolprop-node/src/index.js index c5b98ed..e5b2890 100644 --- a/src/coolprop-node/src/index.js +++ b/src/coolprop-node/src/index.js @@ -3,11 +3,61 @@ const customRefs = require('./refData.js'); class CoolPropWrapper { constructor() { + this.initialized = false; this.defaultRefrigerant = null; this.defaultTempUnit = 'K'; // K, C, F this.defaultPressureUnit = 'Pa' // Pa, kPa, bar, psi this.customRef = false; + this.PropsSI = this._propsSI.bind(this); + + + // 🔹 Wastewater correction options (defaults) + this._ww = { + enabled: true, + tss_g_per_L: 3.5, // default MLSS / TSS + density_k: 2e-4, // +0.02% per g/L + viscosity_k: 0.07, // +7% per g/L (clamped) + viscosity_max_gpl: 4 // cap effect at 4 g/L + }; + + this._initPromise = null; + this._autoInit({ refrigerant: 'Water' }); + + } + + _isWastewaterFluid(fluidRaw) { + if (!fluidRaw) return false; + const token = String(fluidRaw).trim().toLowerCase(); + return token === 'wastewater' || token.startsWith('wastewater:'); + } + + _parseWastewaterFluid(fluidRaw) { + if (!this._isWastewaterFluid(fluidRaw)) return null; + const ww = { ...this._ww }; + const [, tail] = String(fluidRaw).split(':'); + if (tail) { + tail.split(',').forEach(pair => { + const [key, value] = pair.split('=').map(s => s.trim().toLowerCase()); + if (key === 'tss' && !Number.isNaN(Number(value))) { + ww.tss_g_per_L = Number(value); + } + }); + } + return ww; + } + + _applyWastewaterCorrection(outputKey, baseValue, ww) { + if (!Number.isFinite(baseValue) || !ww || !ww.enabled) return baseValue; + switch (outputKey.toUpperCase()) { + case 'D': // density + return baseValue * (1 + ww.density_k * ww.tss_g_per_L); + case 'V': // viscosity + const effTss = Math.min(ww.tss_g_per_L, ww.viscosity_max_gpl); + return baseValue * (1 + ww.viscosity_k * effTss); + default: + return baseValue; + } } // Temperature conversion helpers @@ -407,13 +457,31 @@ class CoolPropWrapper { } } - // Direct access to CoolProp functions - async getPropsSI() { - if(!this.initialized) { - await coolprop.init(); + _autoInit(defaults) { + if (!this._initPromise) { + this._initPromise = this.init(defaults); } - return coolprop.PropsSI; + return this._initPromise; } + + _propsSI(outputKey, inKey1, inVal1, inKey2, inVal2, fluidRaw) { + if (!this.initialized) { + // Start init if no one else asked yet + this._autoInit({ refrigerant: this.defaultRefrigerant || 'Water' }); + throw new Error('CoolProp is still warming up, retry PropsSI in a moment'); + } + const ww = this._parseWastewaterFluid(fluidRaw); + const fluid = ww ? 'Water' : (this.customRefString || fluidRaw); + const baseValue = coolprop.PropsSI(outputKey, inKey1, inVal1, inKey2, inVal2, fluid); + return ww ? this._applyWastewaterCorrection(outputKey, baseValue, ww) : baseValue; + } + + //Access to coolprop + async getPropsSI() { + await this._ensureInit({ refrigerant: this.defaultRefrigerant || 'Water' }); + return this.PropsSI; + } + } module.exports = new CoolPropWrapper(); diff --git a/src/helper/gravity.js b/src/helper/gravity.js new file mode 100644 index 0000000..b6fb568 --- /dev/null +++ b/src/helper/gravity.js @@ -0,0 +1,90 @@ +/** + * Gravity calculations based on WGS-84 ellipsoid model. + * Author: Rene de Ren (Waterschap Brabantse Delta) + * License: EUPL-1.2 + */ + +class Gravity { + constructor() { + // Standard (conventional) gravity at 45° latitude, sea level + this.g0 = 9.80665; // m/s² + } + + /** + * Returns standard gravity (constant) + * @returns {number} gravity in m/s² + */ + getStandardGravity() { + return this.g0; + } + + /** + * Computes local gravity based on latitude and elevation. + * Formula: WGS-84 normal gravity (Somigliana) + * @param {number} latitudeDeg Latitude in degrees (−90 → +90) + * @param {number} elevationM Elevation above sea level [m] + * @returns {number} gravity in m/s² + */ + getLocalGravity(latitudeDeg, elevationM = 0) { + const phi = (latitudeDeg * Math.PI) / 180; + const sinPhi = Math.sin(phi); + const sin2 = sinPhi * sinPhi; + const sin2_2phi = Math.sin(2 * phi) ** 2; + + // WGS-84 normal gravity on the ellipsoid + const gSurface = + 9.780327 * (1 + 0.0053024 * sin2 - 0.0000058 * sin2_2phi); + + // Free-air correction for elevation (~ −3.086×10⁻⁶ m/s² per m) + const gLocal = gSurface - 3.086e-6 * elevationM; + return gLocal; + } + + /** + * Calculates hydrostatic pressure difference (ΔP = ρ g h) + * @param {number} density Fluid density [kg/m³] + * @param {number} heightM Height difference [m] + * @param {number} latitudeDeg Latitude (for local g) + * @param {number} elevationM Elevation (for local g) + * @returns {number} Pressure difference [Pa] + */ + pressureHead(density, heightM, latitudeDeg = 45, elevationM = 0) { + const g = this.getLocalGravity(latitudeDeg, elevationM); + return density * g * heightM; + } + + /** + * Calculates weight force (F = m g) + * @param {number} massKg Mass [kg] + * @param {number} latitudeDeg Latitude (for local g) + * @param {number} elevationM Elevation (for local g) + * @returns {number} Force [N] + */ + weightForce(massKg, latitudeDeg = 45, elevationM = 0) { + const g = this.getLocalGravity(latitudeDeg, elevationM); + return massKg * g; + } +} + +module.exports = new Gravity(); + + +/* +const gravity = gravity; + +// Standard gravity +console.log('g₀ =', gravity.getStandardGravity(), 'm/s²'); + +// Local gravity (Breda ≈ 51.6° N, 3 m elevation) +console.log('g @ Breda =', gravity.getLocalGravity(51.6, 3).toFixed(6), 'm/s²'); + +// Head pressure for 5 m water column at Breda +console.log( + 'ΔP =', + gravity.pressureHead(1000, 5, 51.6, 3).toFixed(1), + 'Pa' +); + +// Weight of 1 kg mass at Breda +console.log('Weight =', gravity.weightForce(1, 51.6, 3).toFixed(6), 'N'); +*/ \ No newline at end of file diff --git a/src/helper/menuUtils.js b/src/helper/menuUtils.js index ebed6b8..4cb6b84 100644 --- a/src/helper/menuUtils.js +++ b/src/helper/menuUtils.js @@ -180,7 +180,6 @@ async apiCall(node) { // Only add tagCode to URL if it exists if (tagCode) { apiUrl += `&asset_tag_number=${tagCode}`; - console.log('hello there'); } assetregisterAPI += apiUrl; @@ -461,10 +460,6 @@ populateModels( // Store only the metadata for the selected model node["modelMetadata"] = modelData.find((model) => model.name === selectedModel); }); - /* - console.log('hello here I am:'); - console.log(node["modelMetadata"]); -*/ }); }) diff --git a/src/helper/menuUtils_DEPRECATED.js b/src/helper/menuUtils_DEPRECATED.js index ebed6b8..95cae41 100644 --- a/src/helper/menuUtils_DEPRECATED.js +++ b/src/helper/menuUtils_DEPRECATED.js @@ -180,7 +180,6 @@ async apiCall(node) { // Only add tagCode to URL if it exists if (tagCode) { apiUrl += `&asset_tag_number=${tagCode}`; - console.log('hello there'); } assetregisterAPI += apiUrl; @@ -461,10 +460,7 @@ populateModels( // Store only the metadata for the selected model node["modelMetadata"] = modelData.find((model) => model.name === selectedModel); }); - /* - console.log('hello here I am:'); - console.log(node["modelMetadata"]); -*/ + }); }) diff --git a/src/helper/outputUtils.js b/src/helper/outputUtils.js index bd6fb8d..744b2ea 100644 --- a/src/helper/outputUtils.js +++ b/src/helper/outputUtils.js @@ -64,7 +64,7 @@ class OutputUtils { influxDBFormat(changedFields, config , flatTags) { // Create the measurement and topic using softwareType and name config.functionality.softwareType + . - const measurement = config.general.name; + const measurement = `${config.functionality?.softwareType}_${config.general?.id}`; const payload = { measurement: measurement, fields: changedFields, @@ -104,24 +104,23 @@ class OutputUtils { return { // general properties id: config.general?.id, - name: config.general?.name, - unit: config.general?.unit, // functionality properties softwareType: config.functionality?.softwareType, role: config.functionality?.role, // asset properties (exclude machineCurve) uuid: config.asset?.uuid, + tagcode: config.asset?.tagcode, geoLocation: config.asset?.geoLocation, - supplier: config.asset?.supplier, + category: config.asset?.category, type: config.asset?.type, - subType: config.asset?.subType, model: config.asset?.model, + unit: config.general?.unit, }; } processFormat(changedFields,config) { // Create the measurement and topic using softwareType and name config.functionality.softwareType + . - const measurement = config.general.name; + const measurement = `${config.functionality?.softwareType}_${config.general?.id}`; const payload = changedFields; const topic = measurement; const msg = { topic: topic, payload: payload }; diff --git a/src/measurements/Measurement.js b/src/measurements/Measurement.js index 761432b..0848657 100644 --- a/src/measurements/Measurement.js +++ b/src/measurements/Measurement.js @@ -113,7 +113,7 @@ class Measurement { // Create a new measurement that is the difference between two positions static createDifference(upstreamMeasurement, downstreamMeasurement) { - console.log('hello:'); + if (upstreamMeasurement.type !== downstreamMeasurement.type || upstreamMeasurement.variant !== downstreamMeasurement.variant) { throw new Error('Cannot calculate difference between different measurement types or variants'); diff --git a/src/menu/asset.js b/src/menu/asset.js index 76933e2..b47dc4d 100644 --- a/src/menu/asset.js +++ b/src/menu/asset.js @@ -1,62 +1,83 @@ -// asset.js -const fs = require('fs'); -const path = require('path'); +const { assetCategoryManager } = require('../../datasets/assetData'); class AssetMenu { - /** Define path where to find data of assets in constructor for now */ - constructor(relPath = '../../datasets/assetData') { - this.baseDir = path.resolve(__dirname, relPath); - this.assetData = this._loadJSON('assetData'); + constructor({ manager = assetCategoryManager, softwareType = null } = {}) { + this.manager = manager; + this.softwareType = softwareType; + this.categories = this.manager + .listCategories({ withMeta: true }) + .reduce((map, meta) => { + map[meta.softwareType] = this.manager.getCategory(meta.softwareType); + return map; + }, {}); } - _loadJSON(...segments) { - const filePath = path.resolve(this.baseDir, ...segments) + '.json'; - try { - return JSON.parse(fs.readFileSync(filePath, 'utf8')); - } catch (err) { - throw new Error(`Failed to load ${filePath}: ${err.message}`); + normalizeCategory(key) { + const category = this.categories[key]; + if (!category) { + return null; } - } - - /** - * ADD THIS METHOD - * Compiles all menu data from the file system into a single nested object. - * This is run once on the server to pre-load everything. - * @returns {object} A comprehensive object with all menu options. - */ - getAllMenuData() { - // load the raw JSON once - const data = this._loadJSON('assetData'); - const allData = {}; - data.suppliers.forEach(sup => { - allData[sup.name] = {}; - sup.categories.forEach(cat => { - allData[sup.name][cat.name] = {}; - cat.types.forEach(type => { - // here: store the full array of model objects, not just names - allData[sup.name][cat.name][type.name] = type.models; - }); - }); - }); - - return allData; + return { + ...category, + label: category.label || category.softwareType || key, + suppliers: (category.suppliers || []).map((supplier) => ({ + ...supplier, + id: supplier.id || supplier.name, + types: (supplier.types || []).map((type) => ({ + ...type, + id: type.id || type.name, + models: (type.models || []).map((model) => ({ + ...model, + id: model.id || model.name, + units: model.units || [] + })) + })) + })) + }; } - /** - * Convert the static initEditor function to a string that can be served to the client - * @param {string} nodeName - The name of the node type - * @returns {string} JavaScript code as a string - */ -getClientInitCode(nodeName) { - // step 1: get the two helper strings - const htmlCode = this.getHtmlInjectionCode(nodeName); - const dataCode = this.getDataInjectionCode(nodeName); - const eventsCode = this.getEventInjectionCode(nodeName); - const saveCode = this.getSaveInjectionCode(nodeName); + resolveCategoryForNode(nodeName) { + const keys = Object.keys(this.categories); + if (keys.length === 0) { + return null; + } + if (this.softwareType && this.categories[this.softwareType]) { + return this.softwareType; + } - return ` + if (nodeName) { + const normalized = typeof nodeName === 'string' ? nodeName.toLowerCase() : nodeName; + if (normalized && this.categories[normalized]) { + return normalized; + } + } + + return keys[0]; + } + + getAllMenuData(nodeName) { + const categoryKey = this.resolveCategoryForNode(nodeName); + const selectedCategories = {}; + + if (categoryKey && this.categories[categoryKey]) { + selectedCategories[categoryKey] = this.normalizeCategory(categoryKey); + } + + return { + categories: selectedCategories, + defaultCategory: categoryKey + }; + } + + getClientInitCode(nodeName) { + const htmlCode = this.getHtmlInjectionCode(nodeName); + const dataCode = this.getDataInjectionCode(nodeName); + const eventsCode = this.getEventInjectionCode(nodeName); + const saveCode = this.getSaveInjectionCode(nodeName); + + return ` // --- AssetMenu for ${nodeName} --- window.EVOLV.nodes.${nodeName}.assetMenu = window.EVOLV.nodes.${nodeName}.assetMenu || {}; @@ -66,103 +87,276 @@ getClientInitCode(nodeName) { ${eventsCode} ${saveCode} - // wire it all up when the editor loads window.EVOLV.nodes.${nodeName}.assetMenu.initEditor = function(node) { - // ------------------ BELOW sequence is important! ------------------------------- - console.log('Initializing asset properties for ${nodeName}…'); + console.log('Initializing asset properties for ${nodeName}'); this.injectHtml(); - // load the data and wire up events - // this will populate the fields and set up the event listeners this.wireEvents(node); - // this will load the initial data into the fields - // this is important to ensure the fields are populated correctly this.loadData(node); }; `; - -} + } -getDataInjectionCode(nodeName) { + getDataInjectionCode(nodeName) { return ` - // Asset Data loader for ${nodeName} + // Asset data loader for ${nodeName} window.EVOLV.nodes.${nodeName}.assetMenu.loadData = function(node) { - const data = window.EVOLV.nodes.${nodeName}.menuData.asset; + const menuAsset = window.EVOLV.nodes.${nodeName}.menuData.asset || {}; + const categories = menuAsset.categories || {}; + const defaultCategory = menuAsset.defaultCategory || Object.keys(categories)[0] || null; const elems = { supplier: document.getElementById('node-input-supplier'), - category: document.getElementById('node-input-category'), - type: document.getElementById('node-input-assetType'), - model: document.getElementById('node-input-model'), - unit: document.getElementById('node-input-unit') + type: document.getElementById('node-input-assetType'), + model: document.getElementById('node-input-model'), + unit: document.getElementById('node-input-unit') }; - function populate(el, opts, sel) { - const old = el.value; - el.innerHTML = ''; - (opts||[]).forEach(o=>{ + + function populate(selectEl, items = [], selectedValue, mapFn, placeholderText = 'Select...') { + const previous = selectEl.value; + const mapper = typeof mapFn === 'function' + ? mapFn + : (value) => ({ value, label: value }); + + selectEl.innerHTML = ''; + + const placeholder = document.createElement('option'); + placeholder.value = ''; + placeholder.textContent = placeholderText; + placeholder.disabled = true; + placeholder.selected = true; + selectEl.appendChild(placeholder); + + items.forEach((item) => { + const option = mapper(item); + if (!option || typeof option.value === 'undefined') { + return; + } const opt = document.createElement('option'); - opt.value = o; opt.textContent = o; - el.appendChild(opt); + opt.value = option.value; + opt.textContent = option.label; + selectEl.appendChild(opt); }); - el.value = sel||""; - if(el.value!==old) el.dispatchEvent(new Event('change')); + + if (selectedValue) { + selectEl.value = selectedValue; + if (!selectEl.value) { + selectEl.value = ''; + } + } else { + selectEl.value = ''; + } + if (selectEl.value !== previous) { + selectEl.dispatchEvent(new Event('change')); + } } - // initial population - populate(elems.supplier, Object.keys(data), node.supplier); + + const resolveCategoryKey = () => { + if (node.softwareType && categories[node.softwareType]) { + return node.softwareType; + } + if (node.category && categories[node.category]) { + return node.category; + } + return defaultCategory; + }; + + const categoryKey = resolveCategoryKey(); + node.category = categoryKey; + const activeCategory = categoryKey ? categories[categoryKey] : null; + + const suppliers = activeCategory ? activeCategory.suppliers : []; + populate( + elems.supplier, + suppliers, + node.supplier, + (supplier) => ({ value: supplier.id || supplier.name, label: supplier.name }), + suppliers.length ? 'Select...' : 'No suppliers available' + ); + + const activeSupplier = suppliers.find( + (supplier) => (supplier.id || supplier.name) === node.supplier + ); + const types = activeSupplier ? activeSupplier.types : []; + populate( + elems.type, + types, + node.assetType, + (type) => ({ value: type.id || type.name, label: type.name }), + activeSupplier ? 'Select...' : 'Awaiting Supplier Selection' + ); + + const activeType = types.find( + (type) => (type.id || type.name) === node.assetType + ); + const models = activeType ? activeType.models : []; + populate( + elems.model, + models, + node.model, + (model) => ({ value: model.id || model.name, label: model.name }), + activeType ? 'Select...' : 'Awaiting Type Selection' + ); + + const activeModel = models.find( + (model) => (model.id || model.name) === node.model + ); + populate( + elems.unit, + activeModel ? activeModel.units || [] : [], + node.unit, + (unit) => ({ value: unit, label: unit }), + activeModel ? 'Select...' : activeType ? 'Awaiting Model Selection' : 'Awaiting Type Selection' + ); }; - ` + `; } -getEventInjectionCode(nodeName) { + getEventInjectionCode(nodeName) { return ` - // Asset Event wiring for ${nodeName} + // Asset event wiring for ${nodeName} window.EVOLV.nodes.${nodeName}.assetMenu.wireEvents = function(node) { - const data = window.EVOLV.nodes.${nodeName}.menuData.asset; + const menuAsset = window.EVOLV.nodes.${nodeName}.menuData.asset || {}; + const categories = menuAsset.categories || {}; + const defaultCategory = menuAsset.defaultCategory || Object.keys(categories)[0] || null; const elems = { supplier: document.getElementById('node-input-supplier'), - category: document.getElementById('node-input-category'), - type: document.getElementById('node-input-assetType'), - model: document.getElementById('node-input-model'), - unit: document.getElementById('node-input-unit') + type: document.getElementById('node-input-assetType'), + model: document.getElementById('node-input-model'), + unit: document.getElementById('node-input-unit') }; - function populate(el, opts, sel) { - const old = el.value; - el.innerHTML = ''; - (opts||[]).forEach(o=>{ + + function populate(selectEl, items = [], selectedValue, mapFn, placeholderText = 'Select...') { + const previous = selectEl.value; + const mapper = typeof mapFn === 'function' + ? mapFn + : (value) => ({ value, label: value }); + + selectEl.innerHTML = ''; + + const placeholder = document.createElement('option'); + placeholder.value = ''; + placeholder.textContent = placeholderText; + placeholder.disabled = true; + placeholder.selected = true; + selectEl.appendChild(placeholder); + + items.forEach((item) => { + const option = mapper(item); + if (!option || typeof option.value === 'undefined') { + return; + } const opt = document.createElement('option'); - opt.value = o; opt.textContent = o; - el.appendChild(opt); + opt.value = option.value; + opt.textContent = option.label; + selectEl.appendChild(opt); }); - el.value = sel||""; - if(el.value!==old) el.dispatchEvent(new Event('change')); + + if (selectedValue) { + selectEl.value = selectedValue; + if (!selectEl.value) { + selectEl.value = ''; + } + } else { + selectEl.value = ''; + } + if (selectEl.value !== previous) { + selectEl.dispatchEvent(new Event('change')); + } } - elems.supplier.addEventListener('change', ()=>{ - populate(elems.category, - elems.supplier.value? Object.keys(data[elems.supplier.value]||{}) : [], - node.category); + + const resolveCategoryKey = () => { + if (node.softwareType && categories[node.softwareType]) { + return node.softwareType; + } + if (node.category && categories[node.category]) { + return node.category; + } + return defaultCategory; + }; + + const getActiveCategory = () => { + const key = resolveCategoryKey(); + return key ? categories[key] : null; + }; + + node.category = resolveCategoryKey(); + + elems.supplier.addEventListener('change', () => { + const category = getActiveCategory(); + const supplier = category + ? category.suppliers.find( + (item) => (item.id || item.name) === elems.supplier.value + ) + : null; + const types = supplier ? supplier.types : []; + populate( + elems.type, + types, + node.assetType, + (type) => ({ value: type.id || type.name, label: type.name }), + supplier ? 'Select...' : 'Awaiting Supplier Selection' + ); + populate(elems.model, [], '', undefined, 'Awaiting Type Selection'); + populate(elems.unit, [], '', undefined, 'Awaiting Type Selection'); }); - elems.category.addEventListener('change', ()=>{ - const s=elems.supplier.value, c=elems.category.value; - populate(elems.type, - (s&&c)? Object.keys(data[s][c]||{}) : [], - node.assetType); + + elems.type.addEventListener('change', () => { + const category = getActiveCategory(); + const supplier = category + ? category.suppliers.find( + (item) => (item.id || item.name) === elems.supplier.value + ) + : null; + const type = supplier + ? supplier.types.find( + (item) => (item.id || item.name) === elems.type.value + ) + : null; + const models = type ? type.models : []; + populate( + elems.model, + models, + node.model, + (model) => ({ value: model.id || model.name, label: model.name }), + type ? 'Select...' : 'Awaiting Type Selection' + ); + populate( + elems.unit, + [], + '', + undefined, + type ? 'Awaiting Model Selection' : 'Awaiting Type Selection' + ); }); - elems.type.addEventListener('change', ()=>{ - const s=elems.supplier.value, c=elems.category.value, t=elems.type.value; - const md = (s&&c&&t)? data[s][c][t]||[] : []; - populate(elems.model, md.map(m=>m.name), node.model); - }); - elems.model.addEventListener('change', ()=>{ - const s=elems.supplier.value, c=elems.category.value, t=elems.type.value, m=elems.model.value; - const md = (s&&c&&t)? data[s][c][t]||[] : []; - const entry = md.find(x=>x.name===m); - populate(elems.unit, entry? entry.units : [], node.unit); + + elems.model.addEventListener('change', () => { + const category = getActiveCategory(); + const supplier = category + ? category.suppliers.find( + (item) => (item.id || item.name) === elems.supplier.value + ) + : null; + const type = supplier + ? supplier.types.find( + (item) => (item.id || item.name) === elems.type.value + ) + : null; + const model = type + ? type.models.find( + (item) => (item.id || item.name) === elems.model.value + ) + : null; + populate( + elems.unit, + model ? model.units || [] : [], + node.unit, + (unit) => ({ value: unit, label: unit }), + model ? 'Select...' : type ? 'Awaiting Model Selection' : 'Awaiting Type Selection' + ); }); }; - ` + `; } -/** - * Generate HTML template for asset fields - */ getHtmlTemplate() { return ` @@ -172,10 +366,6 @@ getEventInjectionCode(nodeName) { -