diff --git a/README.md b/README.md index 8669905a2424a082732a2bcc46025a7300ec64a9..428dfa69c704ad1050a33234fd5ac8de3297ba34 100644 --- a/README.md +++ b/README.md @@ -112,20 +112,40 @@ Move into the `http-bridge` folder and execute the following: ### NGSI-LD Entity Types -| Entity Type | Description | -| ------------------- | ---------------------------------------------------------- | -| ``WeatherObserved`` | Real-time weather conditions (temperature, humidity, etc.) | - -Additional entity types can be added dynamically by extending the Type Mapping Configuration. +| Entity Type | Description | +| --------------------- | ------------------------------------------------------------------------ | +| ``DeviceMeasurement`` | Device measurements which include records of all the sensors registered. | To support more NGSI-LD models: -1. Add a new type mapping in ``typeMaps/`` +1. Add a new type mapping in ``typeMaps/``. See the DeviceMeasurement typemap for the base structure. 2. Extend NGSITranslator.js to handle the new entity type 3. Modify generalControllers.js to process the new queries -## Testing +## Queries & Testing + +You can view the structure of HTTP queries and test the broker/bridge by using the following Postman workspace: + +**https://www.postman.com/retr0dev/workspace/uowm-depe-http-bridge** + +Clone the workspace into your own account and modify it to your needs. + +**Setting up Postman** -In order to test the broker and the http bridge you can use the sample queries provided at the following Postman workspace: +1. Setup the env variables. + - `broker-ip` : localhost if running locally otherwise the IP of your Scorpio broker + - `broker-port` : the port of the Scorpio broker + - `http-bridge-ip` : the IP address of the bridge - **CANNOT BE LOCALHOST** - If you are running the bridge on the same machine as your broker then you need to set the bridge IP to the machine IP. + - `http-bridge-port` : the port of the HTTP bridge +2. Register Context Source + - In the `Scorpio-Registration` POST request you need to add any new entity types you have implemented. +3. Test the broker + - If everything was setup correctly, you can use any of the GET requests to fetch data according to the request you selected. + The format the requests are following (where 'XYZ' is the entity type to fetch ) is: + - XYZ-Realtime : Latest data from the specific type. + - XYZ-Realtime-Attrs : Latest data from the specific type and the specific attribute listed in the params. + - XYZ-Temporal : Data from a specific date range. + - XYZ-Temporal-Attrs : Data from a specific date range and a specific attribute listed in the params. -**https://www.postman.com/payload-geoscientist-32828968/scorpio-broker-registration/overview** +*Note:* +The reason all Realtime requests have a limit on the database entries it will return is because we cannot fetch millions of records from a single query. The server cannot handle that. diff --git a/http-bridge/README.md b/http-bridge/README.md index 12ce0fa23e436f689dd905a34c5f391287b94506..686c3c6955e0658af7cfffa0aeb3cc1922fa09c1 100644 --- a/http-bridge/README.md +++ b/http-bridge/README.md @@ -2,84 +2,8 @@ ## **Overview** -The **HTTP Bridge** serves as a middleware between the **Scorpio Broker** and the **Smart City Heraklion API**. It is responsible for **fetching data from the API**, **translating it into the NGSI-LD format**, and **returning a structured response** that conforms to the **NGSI-LD data model**. +The **HTTP Bridge** serves as a middleware between the **Scorpio Broker** and a **API**. It is responsible for **fetching data from the API**, **translating it into the NGSI-LD format**, and **returning a structured response** that conforms to the **NGSI-LD data model**. --- -## **Getting Started** - -### **1. Prerequisites** -Ensure you have the following installed: -- **Docker** -- **Node.js** (v14 or higher, if running locally) -- **npm** (Node Package Manager) ---- - -### **2. Configuration** -Before running the application, configure the necessary environment variables. - -### **Using `.env` File (Recommended)** -Create a `.env` file in the project root with the following content: - -``` -PORT=9010 # Http Bridge Port -HOST="0.0.0.0" # Http Bridge Host (DONT CHANGE id running with Docker) -API_URL=https://smartcity.heraklion.gr/open-data-api # Base URL of the API -``` - -### **3. Running the HTTP Bridge** -1. Install npm packages -``` -npm install -``` - -2. Build the Docker Image -``` -docker build -t http-bridge . -``` - -3. Run the Container - -``` -docker run -d --name http-bridge -p 8080:8080 --env-file .env http-bridge -``` - -The bridge will be accessible at: **{HOST}:{PORT}** - -Default: **http://localhost:8080** - ---- -### **4. Stopping & Removing the Container** - -1. To stop the running container: -``` -docker stop http-bridge -``` - -2. To remove the container: -``` -docker rm http-bridge -``` - ---- - -## **Supported NGSI-LD Entity Types** -| **Entity Type** | **Description** | -|----------------------|--------------------------------------------------------| -| `WeatherObserved` | Real-time weather conditions (temperature, humidity, etc.) | - -Additional entity types can be added dynamically by extending the **Type Mapping Configuration**. - ---- - -## **Extending the Bridge** -To support more NGSI-LD models, simply: -1. **Add a new type mapping** in `typeMaps/` -2. **Extend `NGSITranslator.js`** to handle the new entity type -3. **Modify `generalControllers.js`** to process the new queries - ---- - -## **Extra Links** -[Scorpio Broker](https://github.com/efntallaris/scorpioBroker) -[Postman Workplace](https://www.postman.com/payload-geoscientist-32828968/workspace/scorpio-broker-registration) \ No newline at end of file +**See the README on the root of this repository for instructions on how to install and setup.** diff --git a/http-bridge/controllers/generalControllers.js b/http-bridge/controllers/generalControllers.js index 7398bbd1349b93a73b17721dc9bf21c0ca4c2df1..91fedefa63855f250a95a5e53a7a3627950a2ee9 100644 --- a/http-bridge/controllers/generalControllers.js +++ b/http-bridge/controllers/generalControllers.js @@ -1,46 +1,41 @@ const axios = require("axios"); +const qs = require("qs"); const NGSITranslator = require("../translator/NGSITranslator"); const typeMaps = require("../typeMaps/typeMaps"); /** - * Generates a modality_id parameter based on the type and attributes provided. - * If attributes are given, it will filter the modalities to only include the ones - * that correspond to the given attributes. Otherwise, it will return all modalities - * available for the given type. - * - * Based on Smart City Heraklion API - * - * @param {string} type The NGSI-LD type to generate the modality_id for + * @param {string} type The NGSI-LD type to generate the measurement_type for * @param {string} attributes A comma-separated list of attributes to filter by * @throws {Error} If the type is invalid or no valid attributes are found - * @returns {string} The modality_id parameter as a string + * @returns {string[]} List of measurement types */ -function generateModalityIdParam(type, attributes) { - const modalityMap = typeMaps[type]; - if (!modalityMap) { +function generateMeasurementTypeParam(type, attributes) { + const typeMap = typeMaps[type]; + if (!typeMap) { throw new Error(`Invalid type: ${type}`); } // Filter attributes if provided, otherwise return all - const modalityIds = attributes - ? attributes.split(",").map(attr => Object.entries(modalityMap) + const measurementTypes = attributes + ? attributes.split(",").map(attr => Object.entries(typeMap) .find(([_, value]) => value.slug === attr)?.[0]) .filter(Boolean) - : Object.keys(modalityMap); + : Object.keys(typeMap); - if (modalityIds.length === 0) { - throw new Error(`No valid attributes found for type: ${type}`); + if (measurementTypes.length === 0) { + throw new Error(`No valid attributes found for type '${type}' and attributes '${attributes}'`); } - return modalityIds; + // console.log("Measurement types:", measurementTypes); + return measurementTypes; } /** - * Fetches data from the Smart City Heraklion API and translates it to NGSI-LD. + * Fetches data from the provided API and translates it to NGSI-LD. * * @param {string} type The NGSI-LD type to retrieve * @param {string} [attrs] A comma-separated list of attributes to filter by - * @param {Function} fetcher The specific fetcher function to use (fetchWeatherObservedTemporalData or fetchWeatherObservedRealTimeData) + * @param {Function} fetcher The specific fetcher function to use (fetchTemporalData or fetchRealTimeData) * @param {Object} [additionalParams] Additional parameters to pass to the fetcher function * @param {Response} res The Express response object * @throws {Error} If the type is invalid, no valid attributes are found, or the API request fails @@ -55,23 +50,20 @@ const fetchEntities = async (type, attrs, fetcher, additionalParams, res) => { return res.status(400).json({ error: `Unsupported entity type: ${type}` }); } - const modalityIdParam = generateModalityIdParam(type, attrs); - if (!modalityIdParam) { - return res.status(400).json({ error: "Missing modality_id parameter." }); + const measurementTypes = generateMeasurementTypeParam(type, attrs); + if (!measurementTypes) { + return res.status(400).json({ error: "Missing measurement_type parameter." }); } - // Call the specific fetcher function - const apiResponse = await fetcher(type, modalityIdParam, additionalParams); - - if (!apiResponse || !apiResponse.data) { - return res.status(500).json({ error: "Failed to retrieve data from API." }); + const apiResponse = await fetcher(type, measurementTypes, additionalParams); + if (!apiResponse || !apiResponse.data || apiResponse.data.length === 0) { + return res.status(500).json({ error: "Failed to retrieve data from API. See http-bridge logs for info." }); } - // Translate response to NGSI-LD const ngsiData = NGSITranslator.toNGSI(apiResponse.data, type); res.status(200).json(ngsiData); } catch (error) { - console.error("Error in fetchEntities:", error.message); + console.error(`error in fetchEntities\n${error.stack}\n`); res.status(500).json({ error: error.message || "Failed to fetch entities." }); } }; @@ -80,67 +72,65 @@ const fetchEntities = async (type, attrs, fetcher, additionalParams, res) => { * Fetches the temporal data for a given NGSI-LD entity type. * * @param {string} type The NGSI-LD type to retrieve - * @param {string} modalityIdParam The modality_id parameter for filtering + * @param {string} measurementTypes The measurement type parameter for filtering * @param {Object} [params] Additional parameters for the API request * @throws {Error} If the entity type is unsupported */ -const fetchWeatherObservedTemporalData = async (type, modalityIds, params) => { - if (!Array.isArray(modalityIds) || modalityIds.length === 0) { - throw new Error(`Invalid modality IDs for type: ${type}`); - } - - const results = { data: [] }; - - // Loop through each modality ID and make separate requests - for (const modalityId of modalityIds) { - try { - const apiResponse = await axios.post(`${process.env.API_URL}/rpc/measurements_averages`, { - _devices: "{71,72,73,63,64,36,68,70,61,69,67,66,65,60,59,120}", - _from: params.time, - _to: params.endTime, - _granularity: "1 hour", - _modality: typeMaps[type][modalityId].key, - _show_out_of_range: false - }); - - if (apiResponse && apiResponse.data) { - formattedData = apiResponse.data.map(entry => ({ - device_id: modalityId, - modality_id: parseInt(modalityId, 10), - value: entry.avg, - observed_at: entry.at - })); - - results.data.push(...formattedData); +const fetchTemporalData = async (type, measurementTypes, params) => { + switch (type) { + case "DeviceMeasurement": + try { + const response = await axios.get(`${process.env.API_URL}/device_measurement`, { + params: { + measurement_type: `in.(${measurementTypes.join(",")})`, + ts: params.ts, + }, + paramsSerializer: (params) => qs.stringify(params, { encode: false }) // Prevent double encoding + }); + + return response; + } catch (error) { + console.error(`error fetching temporal data\n${error.stack}`); + return { data: [] }; } - } catch (error) { - console.error(`Error fetching data for modalityId ${modalityId}:`, error.message); - } - } - return results; + default: + return { data: [] }; + } }; /** * Fetches the latest real-time data for a given NGSI-LD entity type. * * @param {string} type The NGSI-LD type to retrieve - * @param {string} modalityIdParam The modality_id parameter for filtering + * @param {string} measurementTypes The measurement type parameter for filtering * @throws {Error} If the entity type is unsupported */ - -const fetchWeatherObservedRealTimeData = async (type, modalityIdParam) => { +const fetchRealTimeData = async (type, measurementTypes, params) => { switch (type) { - case "WeatherObserved": - return axios.get(`${process.env.API_URL}/latest_measurements_averages`, { - params: { modality_id: `in.(${Array.isArray(modalityIdParam) ? modalityIdParam.join(",") : modalityIdParam})` }, - }); + case "DeviceMeasurement": + try { + const response = await axios.get(`${process.env.API_URL}/device_measurement`, { + params: { + measurement_type: `in.(${measurementTypes.join(",")})`, + order: "ts.desc", + // This is set in order to avoid fetching all data and not + // to overload the system. This can be adjusted as needed. + limit: params.limit || 1000, + } + }); + + return response; + } catch (error) { + console.error(`error fetching real-time data\n${error.stack}`); + return { data: [] }; + } + default: - throw new Error(`Unsupported real-time entity type: ${type}`); + return { data: [] }; } }; - /** * Handles incoming requests for temporal NGSI-LD entities. * @@ -149,26 +139,37 @@ const fetchWeatherObservedRealTimeData = async (type, modalityIdParam) => { * @prop {string} time The timestamp to apply the temporal relationship to * @prop {string} endTime The end time for the time range query * @prop {string} attrs A comma-separated list of attributes to filter by + * @prop {string} limit The maximum number of entities to return */ const getTemporalEntities = async (req, res) => { console.log("Incoming temporal request:", req.query); let { type, timerel, time, endTime, attrs } = req.query; - // Decode URL-encoded time values (fixes %3A issue) - time = decodeURIComponent(time); - if (endTime) endTime = decodeURIComponent(endTime); + let tsParams = []; + + switch (timerel) { + case "after": + tsParams.push(`gte.${time}`); + break; - // Ensure proper ISO 8601 formatting - const now = new Date().toISOString(); + case "before": + const adjustedStartTime = new Date(new Date(time).setDate(new Date(time).getDate() - 30)).toISOString(); + tsParams.push(`gte.${adjustedStartTime}`, `lt.${time}`); + break; - if (timerel === "after") { - endTime = now; // Set endTime to current time - } else if (timerel === "before") { - endTime = time; // Swap values for "before" - time = new Date(new Date(endTime).setDate(new Date(endTime).getDate() - 30)).toISOString(); // 30 days before + case "between": + if (!endTime) { + return res.status(400).json({ error: "endTime is required for 'between' queries" }); + } + tsParams.push(`gte.${time}`, `lt.${endTime}`); + break; + + default: + return res.status(400).json({ error: "Invalid timerel value" }); } - await fetchEntities(type, attrs, fetchWeatherObservedTemporalData, { time, endTime }, res); + // console.log("Final timestamp:", tsParams.join(", ")); + await fetchEntities(type, attrs, fetchTemporalData, { ts: tsParams }, res); }; /** @@ -176,11 +177,13 @@ const getTemporalEntities = async (req, res) => { * * @prop {string} type The NGSI-LD type to retrieve * @prop {string} attrs A comma-separated list of attributes to filter by + * @prop {string} limit The maximum number of entities to return */ const getRealTimeEntities = async (req, res) => { console.log("Incoming real-time request:", req.query); - const { type, attrs } = req.query; - await fetchEntities(type, attrs, fetchWeatherObservedRealTimeData, {}, res); + const { type, attrs, limit } = req.query; + + await fetchEntities(type, attrs, fetchRealTimeData, { limit }, res); }; module.exports = { getTemporalEntities, getRealTimeEntities }; diff --git a/http-bridge/package-lock.json b/http-bridge/package-lock.json index ce4d0df948f99a968125be12ce22c53af3755779..7a3dbc6ed03d536f00c3e44afa2dc5332c543831 100644 --- a/http-bridge/package-lock.json +++ b/http-bridge/package-lock.json @@ -12,13 +12,15 @@ "axios": "^1.7.8", "dotenv": "^16.4.5", "express": "^4.21.1", - "morgan": "^1.10.0" + "morgan": "^1.10.0", + "qs": "^6.14.0" } }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -30,17 +32,20 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/axios": { - "version": "1.7.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", - "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -51,6 +56,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", "dependencies": { "safe-buffer": "5.1.2" }, @@ -61,12 +67,14 @@ "node_modules/basic-auth/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -86,24 +94,51 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -116,6 +151,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -127,6 +163,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -138,6 +175,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -146,6 +184,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -153,36 +192,23 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -191,6 +217,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -199,15 +226,17 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -215,26 +244,40 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -243,6 +286,34 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, "engines": { "node": ">= 0.4" } @@ -250,12 +321,14 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -264,6 +337,7 @@ "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -305,10 +379,26 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -332,6 +422,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -342,12 +433,14 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -358,6 +451,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -366,6 +460,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -374,20 +469,27 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -396,32 +498,36 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -429,10 +535,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { "node": ">= 0.4" }, @@ -444,6 +554,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -455,6 +566,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -470,6 +582,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -480,20 +593,32 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -502,6 +627,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -510,6 +636,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -518,6 +645,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -529,6 +657,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -537,6 +666,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -548,6 +678,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "license": "MIT", "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", @@ -563,6 +694,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -573,20 +705,23 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -598,6 +733,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -609,6 +745,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -617,6 +754,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -624,12 +762,14 @@ "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -641,14 +781,16 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -661,6 +803,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -669,6 +812,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -696,17 +840,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -730,6 +877,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -737,12 +885,14 @@ "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -753,36 +903,76 @@ "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -795,6 +985,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -803,6 +994,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -811,6 +1003,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -823,6 +1016,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -831,6 +1025,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -839,6 +1034,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } diff --git a/http-bridge/package.json b/http-bridge/package.json index cb68f6c55246142b46b75f0895d1e40eb72d96c1..1e9473ad5eba95f415b5b966feb4326484979c0f 100644 --- a/http-bridge/package.json +++ b/http-bridge/package.json @@ -1,5 +1,5 @@ { - "name": "wrappertest", + "name": "uowm-http-bridge", "version": "1.0.0", "main": "index.js", "scripts": { @@ -13,6 +13,7 @@ "axios": "^1.7.8", "dotenv": "^16.4.5", "express": "^4.21.1", - "morgan": "^1.10.0" + "morgan": "^1.10.0", + "qs": "^6.14.0" } } diff --git a/http-bridge/translator/NGSITranslator.js b/http-bridge/translator/NGSITranslator.js index 316d33391bbde2e059c6b855456e8d0fec685cd9..20f88ef6c0e205af005ef66f7fe1da2c5883ee05 100644 --- a/http-bridge/translator/NGSITranslator.js +++ b/http-bridge/translator/NGSITranslator.js @@ -3,14 +3,14 @@ const typeMaps = require("../typeMaps/typeMaps"); class NGSITranslator { static toNGSI(apiData, entityType) { switch (entityType) { - case "WeatherObserved": - return NGSITranslator.processWeatherObserved(apiData, entityType); + case "DeviceMeasurement": + return NGSITranslator.processDeviceMeasurement(apiData, entityType); default: throw new Error(`Unsupported entity type: ${entityType}`); } } - static processWeatherObserved(apiData, entityType) { + static processDeviceMeasurement(apiData, entityType) { const typeMap = typeMaps[entityType]; if (!typeMap) { throw new Error(`No mapping found for entity type: ${entityType}`); @@ -19,7 +19,7 @@ class NGSITranslator { const groupedByDevice = {}; apiData.forEach(item => { - const { device_id, modality_id, value, observed_at } = item; + const { item: device_id, measurement_type, value, ts } = item; // Ensure the device entry exists if (!groupedByDevice[device_id]) { @@ -28,30 +28,30 @@ class NGSITranslator { type: entityType, dateObserved: { type: "Property", values: [] }, "@context": [ - "https://raw.githubusercontent.com/smart-data-models/dataModel.Weather/master/context.jsonld", + "https://raw.githubusercontent.com/smart-data-models/dataModel.Device/master/context.jsonld", "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld" ] }; } - const modalityInfo = typeMap[modality_id]; - if (modalityInfo) { + const measurementInfo = typeMap[measurement_type]; + if (measurementInfo) { // Ensure property exists, else initialize - if (!groupedByDevice[device_id][modalityInfo.key]) { - groupedByDevice[device_id][modalityInfo.key] = { + if (!groupedByDevice[device_id][measurementInfo.key]) { + groupedByDevice[device_id][measurementInfo.key] = { type: "Property", values: [] }; } // Append new observation instead of overwriting - groupedByDevice[device_id][modalityInfo.key].values.push( - NGSITranslator.createProperty(value, modalityInfo.unit, modalityInfo.min, modalityInfo.max, modalityInfo.slug, observed_at) + groupedByDevice[device_id][measurementInfo.key].values.push( + NGSITranslator.createProperty(value, measurementInfo.unit, measurementInfo.min, measurementInfo.max, measurementInfo.slug, ts) ); - // Append observed_at to dateObserved (avoid duplicates) - if (!groupedByDevice[device_id].dateObserved.values.includes(observed_at)) { - groupedByDevice[device_id].dateObserved.values.push(observed_at); + // Append ts to dateObserved (avoid duplicates) + if (!groupedByDevice[device_id].dateObserved.values.includes(ts)) { + groupedByDevice[device_id].dateObserved.values.push(ts); } } }); @@ -61,7 +61,7 @@ class NGSITranslator { static createProperty(value, unit, min, max, slug, observedAt = null) { if (value == null) return undefined; - + return { type: "Property", values: [ @@ -69,6 +69,7 @@ class NGSITranslator { value: value, // Extra data (optional) metadata: { + type: "Property", unitCode: { type: "Property", value: unit }, healthRange: { type: "Property", value: { min, max } }, slug: { type: "Property", value: slug } diff --git a/http-bridge/typeMaps/deviceMeasurementTypeMap.js b/http-bridge/typeMaps/deviceMeasurementTypeMap.js new file mode 100644 index 0000000000000000000000000000000000000000..f8f8c56d109ce6b8f7bdf892b58f653a9622292c --- /dev/null +++ b/http-bridge/typeMaps/deviceMeasurementTypeMap.js @@ -0,0 +1,34 @@ +const deviceMeasurementTypeMap = { + /* + Each entry in the map is a key-value pair where the key is the **type of measurement** and the value is an object with the following properties: + - key: A string representing the name of the property in NGSI format. + - unit: A character string representing the measurement unit for the type. + - min: Min is the minimum possible value for the measurement type. + - max: Max is the maximum possible value for the measurement type. + - slug: The slug is used as "attrs" in the controller, allowing for the selection of specific attributes to be returned in the response. + */ + + "temperature": { key: "temperature", unit: "CEL", min: 0, max: 60, slug: "temperature" }, + "humidity": { key: "humidity", unit: "P1", min: 0, max: 100, slug: "humidity" }, + "energy": { key: "energy", unit: "KWH", min: 0, max: 10000, slug: "energy_consumption" }, + "power": { key: "power", unit: "WTT", min: 0, max: 10000, slug: "power_usage" }, + "luminance": { key: "luminance", unit: "A24", min: 0, max: 1000, slug: "luminance" }, + "barometric pressure": { key: "hectopascal", unit: "A97", min: 0, max: 1200, slug: "pressure" }, + "wind speed": { key: "windSpeed", unit: "KMH", min: 0, max: 50, slug: "wind_speed" }, + "wind angle": { key: "windDirection", unit: "DD", min: 0, max: 359.9, slug: "wind_direction" }, + "CO2": { key: "carbonDioxide", unit: "P1", min: 0, max: 100, slug: "co2" }, + "noise level": { key: "decibel", unit: "2N", min: 0, max: 100, slug: "noise_level" }, + "motion detection switch": { key: "motion", unit: "A99", min: 0, max: 1, slug: "motion_detection" }, + "magnetic switch": { key: "door", unit: "A99", min: 0, max: 1, slug: "magnetic_switch" }, + "UV": { key: "UVIndex", unit: "C62", min: 0, max: 10, slug: "uv" }, +}; + +/* NOTES +* - Percentages are represented as "P1" in the unit field. +* - Luminance is represented as "A24" in the unit field not candela per square meter. +* - Decibels are represented as "2N" in the unit field. +* - Switches are represented as "A99" in the unit field meaning '0' or '1' (bit). +* - UV Index is represented as "C62" in the unit field meaning 'one' (synonym: unit) since UV Index is unitless. +*/ + +module.exports = deviceMeasurementTypeMap; diff --git a/http-bridge/typeMaps/typeMaps.js b/http-bridge/typeMaps/typeMaps.js index fd75277c6a9189fa2bd1db91d3da6b8c939eeaeb..067c363f157aeb97893f4bc93c9fce913c781578 100644 --- a/http-bridge/typeMaps/typeMaps.js +++ b/http-bridge/typeMaps/typeMaps.js @@ -1,9 +1,8 @@ -const weatherObservedTypeMap = require("./weatherObservedTypeMaps"); +const deviceMeasurementTypeMap = require('./deviceMeasurementTypeMap'); // List of all available NGSI-LD model types const typeMaps = { - "WeatherObserved": weatherObservedTypeMap, - // "WaterQualityObserved": waterQualityObservedTypeMap + "DeviceMeasurement": deviceMeasurementTypeMap, }; -module.exports = typeMaps; \ No newline at end of file +module.exports = typeMaps; diff --git a/http-bridge/typeMaps/weatherObservedTypeMaps.js b/http-bridge/typeMaps/weatherObservedTypeMaps.js deleted file mode 100644 index e746d8298a2c07f502b8ae2a29aca55f1630531a..0000000000000000000000000000000000000000 --- a/http-bridge/typeMaps/weatherObservedTypeMaps.js +++ /dev/null @@ -1,19 +0,0 @@ -const weatherObservedTypeMap = { - 1: { key: "ambient_light", unit: "LUX", min: 0, max: 12000, slug: "light" }, - 2: { key: "loudness", unit: "DEC", min: 34.6, max: 85, slug: "noise" }, - 3: { key: "rainfall", unit: "MMT", min: 0, max: 8, slug: "rain" }, - 4: { key: "ambient_temperature", unit: "CEL", min: -10, max: 50, slug: "temperature" }, - 5: { key: "voc", unit: "PPB", min: 0, max: 600, slug: "voc" }, - 6: { key: "sulphurDioxide", unit: "PPB", min: 0, max: 7.09, slug: "so2" }, - 7: { key: "ozone", unit: "PPB", min: 0, max: 47.3, slug: "o3" }, - 8: { key: "nitrogenDioxide", unit: "PPB", min: 0, max: 19.7, slug: "no2" }, - 9: { key: "nitrogenOxide", unit: "PPB", min: 0, max: 25000, slug: "no" }, - 10: { key: "dust", unit: "MCG", min: 0, max: 50, slug: "pm10" }, - 11: { key: "ambient_humidity", unit: "P1", min: 0, max: 100, slug: "humidity" }, - 12: { key: "carbonDioxide", unit: "PPM", min: 0, max: 430, slug: "co2" }, - 13: { key: "atmosphericPressure", unit: "HPA", min: 750, max: 1050, slug: "atmospheric-pressure" }, - 14: { key: "windSpeed", unit: "KMT", min: 0, max: 50, slug: "wind-speed" }, - 15: { key: "windDirection", unit: "DEG", min: 0, max: 359.9, slug: "wind-direction" }, -}; - -module.exports = weatherObservedTypeMap; \ No newline at end of file