diff --git a/src/controllers/tanksController.js b/src/controllers/tanksController.js index 68d11662..e625f35f 100644 --- a/src/controllers/tanksController.js +++ b/src/controllers/tanksController.js @@ -8175,12 +8175,106 @@ exports.validateTankHeight = async (req, reply) => { // } // }; +// exports.compareMeasuredHeight = async (req, reply) => { +// try { +// const { tankName, measuredHeight } = req.body; + +// if (!tankName) { +// return reply.status(400).send({ message: "Tank name is required." }); +// } + +// const tank = await Tank.findOne({ tankName }); +// if (!tank) { +// return reply.status(404).send({ message: "Tank not found." }); +// } + +// const tankHeightFeet = parseFloat(tank.height); +// const tankHeightCm = Math.round(tankHeightFeet * 30.48); + +// const capacityPerCm = parseFloat(tank.waterCapacityPerCm); +// if (!capacityPerCm || capacityPerCm <= 0) { +// return reply.status(400).send({ message: "Invalid waterCapacityPerCm value." }); +// } + +// const manualWaterLevelLiters = parseFloat(tank.waterlevel) || 0; +// const manualWaterLevelInCm = Math.round(manualWaterLevelLiters / capacityPerCm); + +// let sensorWaterLevelInCm = 0; +// let sensorWaterLevelLiters = 0; + +// // Try to get IoT data +// const iotData = await IotData.findOne({ +// hardwareId: tank.hardwareId, +// "tanks.tankhardwareId": tank.tankhardwareId +// }).sort({ date: -1 }); + +// if (iotData) { +// const matchingTank = iotData.tanks.find( +// t => t.tankhardwareId === tank.tankhardwareId +// ); +// if (matchingTank) { +// const tankHeightFromSensor = parseFloat(matchingTank.tankHeight); +// if (!isNaN(tankHeightFromSensor)) { +// const rawSensorWaterLevelInCm = tankHeightCm - Math.round(tankHeightFromSensor); +// sensorWaterLevelInCm = Math.max(0, rawSensorWaterLevelInCm); +// sensorWaterLevelLiters = Math.round(sensorWaterLevelInCm * capacityPerCm); +// } +// } +// } + +// // Include comparison if measuredHeight provided +// let comparison = null; +// if (measuredHeight !== undefined) { +// const measuredHeightNum = parseFloat(measuredHeight); +// if (!isNaN(measuredHeightNum)) { +// const measuredHeightRounded = Math.round(measuredHeightNum); +// const heightDifferenceInCm = Math.abs(manualWaterLevelInCm - measuredHeightRounded); +// const message = heightDifferenceInCm <= 10 +// ? "Manual measurement matches within 10 cm of sensor/manual data." +// : "Manual measurement not matched within range 10 cm."; + +// comparison = { +// measuredHeight: measuredHeightRounded + " cm", +// actualWaterLevelInCm: manualWaterLevelInCm + " cm", +// heightDifferenceInCm: heightDifferenceInCm + " cm", +// message +// }; +// } else { +// comparison = { message: "Invalid measuredHeight; must be a number." }; +// } +// } + +// reply.send({ +// status_code: 200, +// data: { +// tankName: tank.tankName, +// tankHeightInCm: tankHeightCm, +// capacity: tank.capacity, +// manualWaterLevel: manualWaterLevelLiters, // as integer +// manualWaterLevelInCm: manualWaterLevelInCm + " cm", +// sensorWaterLevel: sensorWaterLevelLiters, // as integer +// sensorWaterLevelInCm: sensorWaterLevelInCm + " cm", +// ...(comparison && { comparison }) +// } +// }); + +// } catch (err) { +// console.error(err); +// reply.status(500).send({ message: err.message || "Internal Server Error" }); +// } +// }; + + exports.compareMeasuredHeight = async (req, reply) => { try { - const { tankName, measuredHeight } = req.body; + const { tankName, measuredHeight, tankHeight } = req.body; - if (!tankName) { - return reply.status(400).send({ message: "Tank name is required." }); + if (!tankName || typeof measuredHeight !== 'number' || typeof tankHeight !== 'number') { + return reply.status(400).send({ message: "tankName, tankHeight and measuredHeight (all required, as integers)." }); + } + + if (tankHeight <= 0 || measuredHeight < 0) { + return reply.status(400).send({ message: "Invalid tankHeight or measuredHeight; must be positive numbers." }); } const tank = await Tank.findOne({ tankName }); @@ -8188,21 +8282,16 @@ exports.compareMeasuredHeight = async (req, reply) => { return reply.status(404).send({ message: "Tank not found." }); } - const tankHeightFeet = parseFloat(tank.height); - const tankHeightCm = Math.round(tankHeightFeet * 30.48); - const capacityPerCm = parseFloat(tank.waterCapacityPerCm); if (!capacityPerCm || capacityPerCm <= 0) { - return reply.status(400).send({ message: "Invalid waterCapacityPerCm value." }); + return reply.status(400).send({ message: "Invalid waterCapacityPerCm in tank data." }); } - const manualWaterLevelLiters = parseFloat(tank.waterlevel) || 0; - const manualWaterLevelInCm = Math.round(manualWaterLevelLiters / capacityPerCm); + // 🔹 Sensor data + let sensorGapCm = null; + let sensorWaterLevelInCm = null; + let sensorWaterLevelLiters = null; - let sensorWaterLevelInCm = 0; - let sensorWaterLevelLiters = 0; - - // Try to get IoT data const iotData = await IotData.findOne({ hardwareId: tank.hardwareId, "tanks.tankhardwareId": tank.tankhardwareId @@ -8213,48 +8302,47 @@ exports.compareMeasuredHeight = async (req, reply) => { t => t.tankhardwareId === tank.tankhardwareId ); if (matchingTank) { - const tankHeightFromSensor = parseFloat(matchingTank.tankHeight); - if (!isNaN(tankHeightFromSensor)) { - const rawSensorWaterLevelInCm = tankHeightCm - Math.round(tankHeightFromSensor); - sensorWaterLevelInCm = Math.max(0, rawSensorWaterLevelInCm); + const tankHeightFromSensor = parseInt(matchingTank.tankHeight, 10); + if (!isNaN(tankHeightFromSensor) && tankHeightFromSensor >= 0) { + sensorGapCm = tankHeightFromSensor; + sensorWaterLevelInCm = Math.max(0, tankHeight - sensorGapCm); sensorWaterLevelLiters = Math.round(sensorWaterLevelInCm * capacityPerCm); } } } - // Include comparison if measuredHeight provided - let comparison = null; - if (measuredHeight !== undefined) { - const measuredHeightNum = parseFloat(measuredHeight); - if (!isNaN(measuredHeightNum)) { - const measuredHeightRounded = Math.round(measuredHeightNum); - const heightDifferenceInCm = Math.abs(manualWaterLevelInCm - measuredHeightRounded); - const message = heightDifferenceInCm <= 10 - ? "Manual measurement matches within 10 cm of sensor/manual data." - : "Manual measurement not matched within range 10 cm."; - - comparison = { - measuredHeight: measuredHeightRounded + " cm", - actualWaterLevelInCm: manualWaterLevelInCm + " cm", - heightDifferenceInCm: heightDifferenceInCm + " cm", - message - }; - } else { - comparison = { message: "Invalid measuredHeight; must be a number." }; - } - } + // 🔹 Manual data + const manualWaterLevelInCm = measuredHeight; + const manualWaterLevelLiters = Math.round(manualWaterLevelInCm * capacityPerCm); + + // 🔹 Comparison + const heightDifferenceInCm = Math.abs(manualWaterLevelInCm - (sensorWaterLevelInCm ?? 0)); + const comparisonMessage = heightDifferenceInCm <= 10 + ? "Manual measurement matches within 10 cm of sensor data." + : "Manual measurement not matched within range 10 cm."; reply.send({ status_code: 200, data: { - tankName: tank.tankName, - tankHeightInCm: tankHeightCm, + tankName, + tankHeightInCm: tankHeight, capacity: tank.capacity, - manualWaterLevel: manualWaterLevelLiters, // as integer - manualWaterLevelInCm: manualWaterLevelInCm + " cm", - sensorWaterLevel: sensorWaterLevelLiters, // as integer - sensorWaterLevelInCm: sensorWaterLevelInCm + " cm", - ...(comparison && { comparison }) + sensor: { + tankHeightInCm: tankHeight, + sensorGapCm: sensorGapCm ?? null, + waterLevelInCm: sensorWaterLevelInCm ?? null, + waterLevelLiters: sensorWaterLevelLiters ?? null + }, + manual: { + tankHeightInCm: tankHeight, + //measuredHeightCm: measuredHeight, + waterLevelInCm: manualWaterLevelInCm, + waterLevelLiters: manualWaterLevelLiters + }, + comparison: { + heightDifferenceInCm, + message: comparisonMessage + } } }); @@ -8266,8 +8354,6 @@ exports.compareMeasuredHeight = async (req, reply) => { - - //const ExcelJS = require('exceljs'); //const IotData = require('../models/IotData'); // adjust the path diff --git a/src/routes/tanksRoute.js b/src/routes/tanksRoute.js index 320ee3e3..5a67cb8a 100644 --- a/src/routes/tanksRoute.js +++ b/src/routes/tanksRoute.js @@ -726,33 +726,51 @@ module.exports = function (fastify, opts, next) { - fastify.route({ - method: "POST", - url: "/api/compareWaterLevel", - schema: { - tags: ["Tank"], - description: "Compare measured height with actual water level", - summary: "Checks if measured height is within 10 cm of actual water level", - // params: { - // type: "object", - // properties: { - // tankName: { type: "string" } - // }, - // required: ["tankName"] - // }, - body: { - type: "object", - properties: { - measuredHeight: { type: "string" }, - tankName: { type: "string" } - - }, - required: ["measuredHeight","tankName"] - } - }, - handler: tanksController.compareMeasuredHeight - }); + // fastify.route({ + // method: "POST", + // url: "/api/compareWaterLevel", + // schema: { + // tags: ["Tank"], + // description: "Compare measured height with actual water level", + // summary: "Checks if measured height is within 10 cm of actual water level", + // // params: { + // // type: "object", + // // properties: { + // // tankName: { type: "string" } + // // }, + // // required: ["tankName"] + // // }, + // body: { + // type: "object", + // properties: { + // measuredHeight: { type: "string" }, + // tankName: { type: "string" } + + // }, + // required: ["measuredHeight","tankName"] + // } + // }, + // handler: tanksController.compareMeasuredHeight + // }); +fastify.post('/api/compareMeasuredHeight', { + schema: { + tags: ['Tank'], + summary: 'Compare manual measured height with sensor data', + description: 'Pass tankName, tankHeight (cm) and measuredHeight (cm) as integers. Compares manual measurement vs sensor data and shows water levels.', + body: { + type: 'object', + required: ['tankName', 'tankHeight', 'measuredHeight'], + properties: { + tankName: { type: 'string', example: 'TANK 1 SUMP' }, + tankHeight: { type: 'integer', example: 213 }, // in cm + measuredHeight: { type: 'integer', example: 200 } // in cm + } + }, + + }, + handler: tanksController.compareMeasuredHeight +}); fastify.route({ method: "POST",