From 165bd6ff9e96dbcfb0b8641db342d6b5abeb1bff Mon Sep 17 00:00:00 2001 From: Bhaskar Date: Mon, 27 Jan 2025 16:39:25 +0530 Subject: [PATCH 1/4] changes start and stop --- src/controllers/tanksController.js | 225 +++++++++++++++++++---------- 1 file changed, 152 insertions(+), 73 deletions(-) diff --git a/src/controllers/tanksController.js b/src/controllers/tanksController.js index 8487c018..bec633d9 100644 --- a/src/controllers/tanksController.js +++ b/src/controllers/tanksController.js @@ -1595,25 +1595,64 @@ admin.initializeApp({ // await sendNotification(fcmTokens, 'Motor Started', `Motor ID: ${motorId} started successfully at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`); // }); +// eventEmitter.on( +// 'motorStart', +// async (fcmTokens, timestamp, motorId, waterLevel, blockName, tankName, startTime, motorOnType, stopCriteria, manual_threshold_time) => { +// try { +// // Retrieve the user information +// const users = await User.find({ fcmIds: { $in: fcmTokens } }); +// console.log("users", users); +// const userNames = users.map(user => user.username).join(', '); +// console.log("userNames", userNames); +// const startMethod = motorOnType === "APP" ? "via the App" : "Manual"; + +// // Prepare the message +// const message = +// `🚰 Tank Name: '${tankName}'\n` + +// `🕒 Pump started at: '${startTime}'\n` + +// `👤 Started by : ${userNames}\n` + +// // `Pump started by: '${motorOnType.toUpperCase()}'\n` + +// `Mode : '${startMethod}'\n` + +// `Will stop at after: '${manual_threshold_time}' mins`; + +// // Send the notification +// await sendNotification(fcmTokens, 'Arminta Water Management', message); +// } catch (error) { +// console.error('Error in motorStart event:', error); +// } +// } +// ); + +// Event listener for motorStart eventEmitter.on( 'motorStart', - async (fcmTokens, timestamp, motorId, waterLevel, blockName, tankName, startTime, motorOnType, stopCriteria, manual_threshold_time) => { + async (fcmTokens, tankName, blockName, startTime, motorOnType, manual_threshold_time, typeOfWater) => { try { // Retrieve the user information const users = await User.find({ fcmIds: { $in: fcmTokens } }); console.log("users", users); const userNames = users.map(user => user.username).join(', '); console.log("userNames", userNames); - const startMethod = motorOnType === "APP" ? "via the App" : "Manual"; + + const startMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual"; + + // Generate motor name dynamically based on tank name, block name, and type of water + const motorName = `${tankName}-${blockName}-${typeOfWater}`; + + // Get current date and time for the motor start time + const currentDateTime = new Date(); + const formattedDate = currentDateTime.toLocaleDateString(); // Customize this format as needed + const formattedTime = currentDateTime.toLocaleTimeString(); // Customize this format as needed // Prepare the message const message = + `🚰 Motor Name: ${motorName}\n` + `🚰 Tank Name: '${tankName}'\n` + - `🕒 Pump started at: '${startTime}'\n` + - `👤 Initiated by : ${userNames}\n` + - // `Pump started by: '${motorOnType.toUpperCase()}'\n` + - `🔄 Pump started by: '${startMethod}'\n` + - `Will stop at after: '${manual_threshold_time}' mins`; + `🚰 Block Name: '${blockName}'\n` + + `👤 Started by: ${userNames}\n` + + `📱 Mode: '${startMethod}'\n` + + `🕒 Pump started at: ${startTime} (Time: ${formattedTime} on ${formattedDate})\n` + + `Will stop after: '${manual_threshold_time}' mins`; // Send the notification await sendNotification(fcmTokens, 'Arminta Water Management', message); @@ -1623,33 +1662,71 @@ eventEmitter.on( } ); +// Event listener for motorStop +eventEmitter.on( + 'motorStop', + async (fcmTokens, tankName, blockName, stopTime, motorOnType, totalWaterPumped, typeOfWater) => { + try { + // Retrieve the user information + const users = await User.find({ fcmIds: { $in: fcmTokens } }); + const userNames = users.map(user => user.username).join(', '); + + const stopMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual"; -eventEmitter.on('motorStop', async (fcmTokens, tankName,stopTime, motorOnType) => { - try { - // Retrieve the user information - const users = await User.find({ fcmIds: { $in: fcmTokens } }); - console.log("users",users) - const userNames = users.map(user => user.username).join(', '); - console.log("userNames",userNames) - - const stopMethod = motorOnType === "APP" ? "via the App" : "manual"; - - // Prepare the message - // const message = `Tank Name: '${tankName}', Pump stopped at '${stopTime}' by Initiated by user(s): ${userNames} '${motorOnType}'`; - const message = - `🚰 Tank Name: '${tankName}'\n` + - `🕒 Pump stopped at: '${stopTime}'\n` + - `👤 Initiated by : ${userNames}\n` + - // `Motor Off Type: '${motorOnType}'`; - `Motor Off Type: '${stopMethod}'`; + // Generate motor name dynamically based on tank name, block name, and type of water + const motorName = `${tankName}-${blockName}-${typeOfWater}`; - - // Send the notification - await sendNotification(fcmTokens, 'Arminta Water Management', message); - } catch (error) { - console.error('Error in motorStart event:', error); + // Get current date and time for the motor stop time + const currentDateTime = new Date(); + const formattedDate = currentDateTime.toLocaleDateString(); // Customize this format as needed + const formattedTime = currentDateTime.toLocaleTimeString(); // Customize this format as needed + + // Prepare the message + const message = + `🚰 Motor Name: ${motorName}\n` + + `🚰 Tank Name: '${tankName}'\n` + + `🚰 Block Name: '${blockName}'\n` + + `👤 Stopped by: ${userNames}\n` + + `📱 Mode: '${stopMethod}'\n` + + `🕒 Pump stopped at: ${stopTime} (Time: ${formattedTime} on ${formattedDate})\n` + + `💧 Total water pumped: ${totalWaterPumped} liters\n`; // Ensure this line is properly terminated + + // Send the notification + await sendNotification(fcmTokens, 'Arminta Water Management', message); + } catch (error) { + console.error('Error in motorStop event:', error); + } } -}); +); + + + +// eventEmitter.on('motorStop', async (fcmTokens, tankName,stopTime, motorOnType) => { +// try { +// // Retrieve the user information +// const users = await User.find({ fcmIds: { $in: fcmTokens } }); +// console.log("users",users) +// const userNames = users.map(user => user.username).join(', '); +// console.log("userNames",userNames) + +// const stopMethod = motorOnType === "Mobile APP" ? "via the App" : "manual"; + +// // Prepare the message +// // const message = `Tank Name: '${tankName}', Pump stopped at '${stopTime}' by Initiated by user(s): ${userNames} '${motorOnType}'`; +// const message = +// `🚰 Tank Name: '${tankName}'\n` + +// `🕒 Pump stopped at: '${stopTime}'\n` + +// `👤 Initiated by : ${userNames}\n` + +// // `Motor Off Type: '${motorOnType}'`; +// `Motor Off Type: '${stopMethod}'`; + + +// // Send the notification +// await sendNotification(fcmTokens, 'Arminta Water Management', message); +// } catch (error) { +// console.error('Error in motorStart event:', error); +// } +// }); // Emit motor stop event with motorId // eventEmitter.on('motorStop', async (fcmTokens, timestamp, motorId, waterLevel, blockName, tankName,stopTime,motorOnType) => { @@ -2314,6 +2391,17 @@ const monitorWaterLevels = async () => { setInterval(monitorWaterLevels, 30 * 60 * 1000); const motorIntervals = {}; +async function calculateTotalPumpedWater(customerId, motorId, start_instance_id) { + const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id }); + if (motorData) { + const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() }); + const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10); + const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10); + const waterPumpedTillNow = parseInt(receiverTank.total_water_added_from_midnight, 10); + return quantityDelivered + waterPumpedTillNow; // Total water pumped + } + return 0; // Return 0 if no data found +} exports.motorAction = async (req, reply) => { try { const customerId = req.params.customerId; @@ -2340,7 +2428,8 @@ exports.motorAction = async (req, reply) => { console.log(receiverTank) const currentWaterLevel = parseInt(receiverTank.waterlevel, 10); const waterLevelThresholds = { low: 30, veryLow: 20, criticallyLow: 10 }; - + const typeOfWater = receiverTank.typeOfWater; + console.log(typeOfWater,"typeOfWater") // Determine the motor stop status based on the action let motorStopStatus; @@ -2362,39 +2451,25 @@ exports.motorAction = async (req, reply) => { ); const thresholdTimeMs = req.body.manual_threshold_time * 60 * 1000; // Convert minutes to milliseconds - const stopCriteria = + const stopCriteria = motorOnType === "time" ? `${req.body.manual_threshold_time} minutes` : `${req.body.manual_threshold_litres} litres`; await checkWaterLevelsAndNotify(customerId, tankName, receiverTank.tankLocation, fcmToken); - - // eventEmitter.emit( - // "motorStart", - // fcmToken, - // new Date().toISOString(), - // motorId, - // currentWaterLevel, - // blockName, // Block Name - // tankName, // Tank Name - // startTime, - // motorOnType, - // stopCriteria, - // manual_threshold_time - // ); + if (!notificationSentStatus.motorStart) { eventEmitter.emit( - "motorStart", - fcmToken, - new Date().toISOString(), - motorId, - currentWaterLevel, - blockName, - tankName, - startTime, - "APP", - manual_threshold_time + 'motorStart', + fcmToken, + tankName, + blockName, + startTime, + "Mobile APP", + manual_threshold_time, + typeOfWater ); + notificationSentStatus.motorStart = true; // Set flag to true to prevent duplicate notifications } await Tank.updateOne( @@ -2405,17 +2480,6 @@ exports.motorAction = async (req, reply) => { "connections.inputConnections.$.motor_on_type": motorOnType } } ); - // await Tank.updateOne( - // { customerId, "connections.inputConnections.motor_id": motorId }, - // { - // $set: { - // "connections.inputConnections.$.motor_stop_status": "2", - // "connections.inputConnections.$.motor_on_type": "manual", - // } - // } - // ); - - reply.code(200).send({ message: "Motor started successfully." }); } else if (action === "stop") { @@ -2434,13 +2498,28 @@ exports.motorAction = async (req, reply) => { // stopTime, // motorOnType // ); + + if (!notificationSentStatus.motorStop) { + // eventEmitter.emit( + // "motorStop", + // fcmToken, + // tankName, + // stopTime, + // "APP" + // ); + + // Emit motorStop event + const totalWaterPumped = await calculateTotalPumpedWater(customerId, motorId, start_instance_id); // A function to calculate total water pumped eventEmitter.emit( - "motorStop", - fcmToken, - tankName, - stopTime, - "APP" + 'motorStop', + fcmToken, + tankName, + blockName, + stopTime, + "Mobile APP", + totalWaterPumped, // Include total water pumped + typeOfWater ); notificationSentStatus.motorStop = true; // Set flag to true to prevent duplicate notifications } From 511b790b663a23df99dac000ada9567be5e305c6 Mon Sep 17 00:00:00 2001 From: Bhaskar Date: Mon, 27 Jan 2025 17:00:42 +0530 Subject: [PATCH 2/4] get all zones and cities --- src/controllers/departmentController.js | 53 +++++++++++++++------- src/routes/departmentRoute.js | 60 ++++++++++++++++++------- 2 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/controllers/departmentController.js b/src/controllers/departmentController.js index f9d27eec..b3302718 100644 --- a/src/controllers/departmentController.js +++ b/src/controllers/departmentController.js @@ -132,21 +132,21 @@ const generateDepartmentId = async (city, departmentName) => { // } // }; - exports.getallcities = async (req, reply) => { - try { - await City.find() - .exec() - .then((docs) => { - reply.send({ status_code: 200, data: docs, count: docs.length }); - }) - .catch((err) => { - console.log(err); - reply.send({ error: err }); - }); - } catch (err) { - throw boom.boomify(err); - } - }; + // exports.getallcities = async (req, reply) => { + // try { + // await City.find() + // .exec() + // .then((docs) => { + // reply.send({ status_code: 200, data: docs, count: docs.length }); + // }) + // .catch((err) => { + // console.log(err); + // reply.send({ error: err }); + // }); + // } catch (err) { + // throw boom.boomify(err); + // } + // }; // exports.getAllDepartmentsParticularFields = async (req, reply) => { @@ -423,6 +423,29 @@ exports.addDepartment = async (request, reply) => { throw boom.boomify(err); } }; + + exports.getallCitiesData = async (req, reply) => { + try { + console.log("Fetching all cities..."); // Debug log + const cities = await Deparments.distinct('city'); // Use distinct to get unique cities + console.log("Cities fetched:", cities); // Log the fetched cities + reply.send({ status_code: 200, data: cities, count: cities.length }); + } catch (err) { + console.error("Error fetching cities:", err); // Log the error for debugging + throw boom.boomify(err); + } + }; + + exports.getallZonesData = async (req, reply) => { + try { + console.log("Fetching all zones..."); // Debug log + const zones = await Deparments.distinct('zone'); + reply.send({ status_code: 200, data: zones, count: zones.length }); + } catch (err) { + console.error("Error fetching cities:", err); // Log the error for debugging + throw boom.boomify(err); + } + }; exports.deletedepartmentInfo = async (req, reply) => { try { diff --git a/src/routes/departmentRoute.js b/src/routes/departmentRoute.js index ece82516..5b51b0fd 100644 --- a/src/routes/departmentRoute.js +++ b/src/routes/departmentRoute.js @@ -62,21 +62,21 @@ module.exports = function (fastify, opts, next) { // handler: departmentController.getSinledepartmentData, // }); - fastify.get("/api/getallcities", { - schema: { - tags: ["Department"], - description: "This is for Get all cities Data", - summary: "This is for to Get all cities Data", + // fastify.get("/api/getallcities", { + // schema: { + // tags: ["Department"], + // description: "This is for Get all cities Data", + // summary: "This is for to Get all cities Data", - security: [ - { - basicAuth: [], - }, - ], - }, - //preHandler: fastify.auth([fastify.authenticate]), - handler: departmentController.getallcities, - }); + // security: [ + // { + // basicAuth: [], + // }, + // ], + // }, + // //preHandler: fastify.auth([fastify.authenticate]), + // handler: departmentController.getallcities, + // }); // fastify.get("/api/getalldepartmentsParticularFileds", { @@ -235,7 +235,37 @@ module.exports = function (fastify, opts, next) { //preHandler: fastify.auth([fastify.authenticate]), handler: departmentController.getalldepartments, }); - + + fastify.get("/api/getallcitiesdata", { + schema: { + tags: ["Department"], + description: "This is for Get all Cities Data", + summary: "This is for to Get all Cities Data", + + security: [ + { + basicAuth: [], + }, + ], + }, + //preHandler: fastify.auth([fastify.authenticate]), + handler: departmentController.getallCitiesData, + }); + fastify.get("/api/getallzonesdata", { + schema: { + tags: ["Department"], + description: "This is for Get all Zones Data", + summary: "This is for to Get all Zones Data", + + security: [ + { + basicAuth: [], + }, + ], + }, + //preHandler: fastify.auth([fastify.authenticate]), + handler: departmentController.getallZonesData, + }); fastify.delete("/api/deletedepartment/:departmentId", { schema: { description: "Delete a Department by departmentId", From ee968ce27d3d2c84a4dfd069d51fd76780c719a8 Mon Sep 17 00:00:00 2001 From: Varun Date: Tue, 28 Jan 2025 11:27:39 +0530 Subject: [PATCH 3/4] changes --- src/controllers/tanksController.js | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/controllers/tanksController.js b/src/controllers/tanksController.js index 09bbee2a..93fed795 100644 --- a/src/controllers/tanksController.js +++ b/src/controllers/tanksController.js @@ -5353,17 +5353,17 @@ client.on('message', async (topic, message) => { inputConnection.motor_on_type = "forced_manual"; inputConnection.startTime = currentTime; // Emit motor start notification with tankName - eventEmitter.emit( - "sendMotorStartNotification", - fcmToken, // FCM tokens - hw_Id, // Motor ID - inputConnection.water_level || 0, // Water level - motorTank.blockName || "N/A", // Block name - tankName, // Tank name - inputConnection.motor_on_type, // Motor on type - "threshold", // Stop criteria - manual_threshold_time // Threshold time in mins - ); + // eventEmitter.emit( + // "sendMotorStartNotification", + // fcmToken, // FCM tokens + // hw_Id, // Motor ID + // inputConnection.water_level || 0, // Water level + // motorTank.blockName || "N/A", // Block name + // tankName, // Tank name + // inputConnection.motor_on_type, // Motor on type + // "threshold", // Stop criteria + // manual_threshold_time // Threshold time in mins + // ); } @@ -5371,15 +5371,15 @@ client.on('message', async (topic, message) => { inputConnection.motor_stop_status = "1"; // Emit motor stop notification with tankName - eventEmitter.emit( - "sendMotorStopNotification", - fcmToken, // FCM tokens - hw_Id, // Motor ID - inputConnection.water_level || 0, // Water level - motorTank.blockName || "N/A", // Block name - tankName, // Tank name - inputConnection.motor_on_type // Motor on type - ); + // eventEmitter.emit( + // "sendMotorStopNotification", + // fcmToken, // FCM tokens + // hw_Id, // Motor ID + // inputConnection.water_level || 0, // Water level + // motorTank.blockName || "N/A", // Block name + // tankName, // Tank name + // inputConnection.motor_on_type // Motor on type + // ); } await motorTank.save(); // Save the updated tank From 321e09cd5b1ac116175e6ead57d5082bdf523201 Mon Sep 17 00:00:00 2001 From: Bhaskar Date: Tue, 28 Jan 2025 14:19:31 +0530 Subject: [PATCH 4/4] notification chnages --- src/controllers/tanksController.js | 820 ++++++++++++++++++++++------- 1 file changed, 644 insertions(+), 176 deletions(-) diff --git a/src/controllers/tanksController.js b/src/controllers/tanksController.js index 09bbee2a..2a3fe73e 100644 --- a/src/controllers/tanksController.js +++ b/src/controllers/tanksController.js @@ -1758,39 +1758,39 @@ eventEmitter.on( // }); // Event listener to handle notification -eventEmitter.on('sendLowWaterNotification', async (fcmToken, tankInfo) => { - const message = formatWaterLevelMessage(tankInfo, 'low'); - sendNotification(fcmToken, message); -}); +// eventEmitter.on('sendLowWaterNotification', async (fcmToken, tankInfo) => { +// const message = formatWaterLevelMessage(tankInfo, 'low'); +// sendNotification(fcmToken, message); +// }); -eventEmitter.on('sendVeryLowWaterNotification', async (fcmToken, tankInfo) => { - const message = formatWaterLevelMessage(tankInfo, 'very low'); - sendNotification(fcmToken, message); -}); +// eventEmitter.on('sendVeryLowWaterNotification', async (fcmToken, tankInfo) => { +// const message = formatWaterLevelMessage(tankInfo, 'very low'); +// sendNotification(fcmToken, message); +// }); -eventEmitter.on('sendCriticalLowWaterNotification', async (fcmToken, tankInfo) => { - const message = formatWaterLevelMessage(tankInfo, 'critically low'); - sendNotification(fcmToken, message); -}); +// eventEmitter.on('sendCriticalLowWaterNotification', async (fcmToken, tankInfo) => { +// const message = formatWaterLevelMessage(tankInfo, 'critically low'); +// sendNotification(fcmToken, message); +// }); -const formatWaterLevelMessage = (tankInfo, levelType) => { - const tankName = tankInfo.tankName; - const tankLocation = tankInfo.tankLocation; - const waterLevel = parseInt(tankInfo.waterlevel, 10); - const capacity = parseInt(tankInfo.capacity, 10); - const volumeInLitres = (capacity * waterLevel) / 100; // assuming the capacity is in litres - - let levelDescription = ''; - if (levelType === 'low') { - levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`; - } else if (levelType === 'very low') { - levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`; - } else if (levelType === 'critically low') { - levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`; - } +// const formatWaterLevelMessage = (tankInfo, levelType) => { +// const tankName = tankInfo.tankName; +// const tankLocation = tankInfo.tankLocation; +// const waterLevel = parseInt(tankInfo.waterlevel, 10); +// const capacity = parseInt(tankInfo.capacity, 10); +// const volumeInLitres = (capacity * waterLevel) / 100; // assuming the capacity is in litres + +// let levelDescription = ''; +// if (levelType === 'low') { +// levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`; +// } else if (levelType === 'very low') { +// levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`; +// } else if (levelType === 'critically low') { +// levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`; +// } - return `Water level in '${tankName}', located at '${tankLocation}', type of water: ${tankInfo.waterType} is ${levelType} at ${levelDescription}. Action: start motor now.`; -}; +// return `Water level in '${tankName}', located at '${tankLocation}', type of water: ${tankInfo.waterType} is ${levelType} at ${levelDescription}. Action: start motor now.`; +// }; // Emit low water level event with motorId // eventEmitter.on('lowWaterLevel', async (fcmTokens, timestamp, motorId, waterLevel) => { @@ -1827,52 +1827,201 @@ eventEmitter.on('sendThresholdTimeNotification', async (fcmTokens, message) => { } }); +// eventEmitter.on( +// 'sendMotorStartNotification', +// async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType, stopCriteria, manual_threshold_time) => { +// try { +// // Get the latest timestamp +// const startTime = new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); + +// // Retrieve the user information +// const users = await User.find({ fcmIds: { $in: fcmTokens } }); +// const userNames = users.map(user => user.username).join(', '); +// const startMethod = motorOnType.toUpperCase() === "Forced Manual"; + +// // Prepare the message +// const message = +// `🚰 Tank Name: '${tankName}'\n` + +// `🕒 Pump started at: '${startTime}'\n` + +// `👤 Initiated by: ${userNames}\n` + +// `🔄 Pump started by: '${startMethod}'`; + +// // Send the notification +// await sendNotification(fcmTokens, 'Motor Started 🚀', message); +// console.log('Motor start notification sent successfully!'); +// } catch (error) { +// console.error('Error in sendMotorStartNotification event:', error); +// } +// } +// ); + eventEmitter.on( 'sendMotorStartNotification', - async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType, stopCriteria, manual_threshold_time) => { + async ( + fcmTokens, + blockName, + tankName, + motorOnType, + stopCriteria, + typeOfWater, + highThreshold // Add the high threshold as a parameter + ) => { try { // Get the latest timestamp - const startTime = new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); + const currentDateTime = new Date(); + const startTime = currentDateTime.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); + const formattedDate = currentDateTime.toLocaleDateString('en-IN', { timeZone: 'Asia/Kolkata' }); + const formattedTime = currentDateTime.toLocaleTimeString('en-IN', { timeZone: 'Asia/Kolkata' }); // Retrieve the user information const users = await User.find({ fcmIds: { $in: fcmTokens } }); const userNames = users.map(user => user.username).join(', '); - const startMethod = motorOnType.toUpperCase() === "Forced Manual"; - // Prepare the message + // Determine the pump initiation method + const startMethod = motorOnType === "Forced Manual" ? "Physically" : "Manually" + + // Dynamically generate the motor name + const motorName = `${tankName}-${blockName}-${typeOfWater}`; + + // Determine the stop condition message + let stopConditionMessage = ""; + if (stopCriteria === "manual") { + stopConditionMessage = `Will stop at Manually \n`; + } else if (stopCriteria === "highThreshold") { + stopConditionMessage = `🚨 Pump will stop when the water level reaches the high threshold of ${highThreshold}%.\n`; + } + + // Prepare the notification message const message = + `🚰 Motor Name: ${motorName}\n` + `🚰 Tank Name: '${tankName}'\n` + - `🕒 Pump started at: '${startTime}'\n` + - `👤 Initiated by: ${userNames}\n` + - `🔄 Pump started by: '${startMethod}'`; + `🏢 Block Name: '${blockName}'\n` + + `👤 Started by: ${userNames}\n` + + `📱 Mode: '${startMethod}'\n` + + `🕒 Pump started at: ${startTime} (Time: ${formattedTime} on ${formattedDate})\n` + + stopConditionMessage; // Add only the relevant stop condition // Send the notification await sendNotification(fcmTokens, 'Motor Started 🚀', message); - console.log('Motor start notification sent successfully!'); + console.log('Motor start notification with stop criteria sent successfully!'); } catch (error) { console.error('Error in sendMotorStartNotification event:', error); } } ); + +// eventEmitter.on( +// 'sendMotorStartNotification', +// async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType, stopCriteria, manual_threshold_time, typeOfWater) => { +// try { +// // Get the latest timestamp +// const currentDateTime = new Date(); +// const startTime = currentDateTime.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); +// const formattedDate = currentDateTime.toLocaleDateString('en-IN', { timeZone: 'Asia/Kolkata' }); +// const formattedTime = currentDateTime.toLocaleTimeString('en-IN', { timeZone: 'Asia/Kolkata' }); + +// // Retrieve the user information +// const users = await User.find({ fcmIds: { $in: fcmTokens } }); +// const userNames = users.map(user => user.username).join(', '); + +// // Determine the pump initiation method +// const startMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual"; + +// // Dynamically generate the motor name +// const motorName = `${tankName}-${blockName}-${typeOfWater}`; + +// // Prepare the notification message +// const message = +// `🚰 Motor Name: '${motorName}'\n` + +// `🚰 Tank Name: '${tankName}'\n` + +// `🏢 Block Name: '${blockName}'\n` + +// `💧 Water Level: '${waterLevel}%'\n` + +// `👤 Initiated by: ${userNames}\n` + +// `📱 Pump started by: '${startMethod}'\n` + +// `🕒 Start Time: '${startTime}'\n` + +// `⏳ Will stop after: '${manual_threshold_time}' mins\n` + +// `📅 Date: '${formattedDate}'\n` + +// `⏰ Time: '${formattedTime}'`; + +// // Send the notification +// await sendNotification(fcmTokens, 'Motor Started 🚀', message); +// console.log('Motor start notification sent successfully!'); +// } catch (error) { +// console.error('Error in sendMotorStartNotification event:', error); +// } +// } +// ); + + +// eventEmitter.on( +// 'sendMotorStopNotification', +// async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType) => { +// try { +// // Get the latest timestamp +// const stopTime = new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); + +// // Retrieve the user information +// const users = await User.find({ fcmIds: { $in: fcmTokens } }); +// const userNames = users.map(user => user.username).join(', '); +// const stopMethod = motorOnType.toUpperCase() === "Forced Manual"; + +// // Prepare the message +// const message = +// `🚰 Tank Name: '${tankName}'\n` + +// `🕒 Pump stopped at: '${stopTime}'\n` + +// `👤 Initiated by: ${userNames}\n` + +// `🔄 Pump stopped by: '${stopMethod}'\n`; + +// // Send the notification +// await sendNotification(fcmTokens, 'Motor Stopped 🛑', message); +// console.log('Motor stop notification sent successfully!'); +// } catch (error) { +// console.error('Error in sendMotorStopNotification event:', error); +// } +// } +// ); + eventEmitter.on( 'sendMotorStopNotification', - async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType) => { + async ( + fcmTokens, + blockName, + tankName, + motorOnType, + typeOfWater + ) => { try { // Get the latest timestamp - const stopTime = new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); + const currentDateTime = new Date(); + const stopTime = currentDateTime.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }); + const formattedDate = currentDateTime.toLocaleDateString('en-IN', { timeZone: 'Asia/Kolkata' }); + const formattedTime = currentDateTime.toLocaleTimeString('en-IN', { timeZone: 'Asia/Kolkata' }); // Retrieve the user information const users = await User.find({ fcmIds: { $in: fcmTokens } }); const userNames = users.map(user => user.username).join(', '); - const stopMethod = motorOnType.toUpperCase() === "Forced Manual"; - // Prepare the message + // Determine the pump stop method + const stopMethod = motorOnType === "Forced Manual" ? "Physically" : "Manually"; + + // Dynamically generate the motor name + const motorName = `${tankName}-${blockName}-${typeOfWater}`; + // Determine the stop condition message + let stopConditionMessage = ""; + if (stopCriteria === "manual") { + stopConditionMessage = `Stopped at Manually \n`; + } else if (stopCriteria === "highThreshold") { + stopConditionMessage = `🚨 Pump will stop when the water level reaches the high threshold of ${highThreshold}%.\n`; + } + // Prepare the notification message const message = + `🚰 Motor Name: ${motorName}\n` + `🚰 Tank Name: '${tankName}'\n` + - `🕒 Pump stopped at: '${stopTime}'\n` + - `👤 Initiated by: ${userNames}\n` + - `🔄 Pump stopped by: '${stopMethod}'\n`; + `🏢 Block Name: '${blockName}'\n` + + `📱 Mode: '${stopMethod}'\n` + + `🕒 Pump stopped at: ${stopTime} (Time: ${formattedTime} on ${formattedDate})\n` + + stopConditionMessage; // Send the notification await sendNotification(fcmTokens, 'Motor Stopped 🛑', message); @@ -1883,6 +2032,31 @@ eventEmitter.on( } ); +eventEmitter.on('sendLowWaterNotification', (fcmTokens, message) => { + const notificationMessage = `Warning: Water level is low in the tank. + Tank Name: ${tankName}, + Location: ${receiverTank.location}, + Type of Water: ${receiverTank.typeOfWater}, + Current Water Level: ${currentWaterLevel} liters (${currentWaterPercentage.toFixed(2)}%), + Date & Time: ${new Date().toLocaleString()}`; + + // Send notifications using the provided FCM tokens + sendNotification(fcmTokens, notificationMessage); +}); + +eventEmitter.on('sendCriticalLowWaterNotification', (fcmTokens, message) => { + const notificationMessage = `Critical Alert: Water level is critically low in the tank. + Tank Name: ${tankName}, + Location: ${receiverTank.location}, + Type of Water: ${receiverTank.typeOfWater}, + Current Water Level: ${currentWaterLevel} liters (${currentWaterPercentage.toFixed(2)}%), + Date & Time: ${new Date().toLocaleString()}`; + + // Send notifications using the provided FCM tokens + sendNotification(fcmTokens, notificationMessage); +}); + + // eventEmitter.on('sendMotorStartNotification', async (fcmTokens, message) => { // try { @@ -1956,12 +2130,21 @@ const sendNotification = async (fcmIds, title, body) => { notification: { title, body }, token, data: { - 'target': '/route_navigation', + 'target': '/screen', }, }); console.log(`Notification sent successfully to token: ${token}`, response); } catch (error) { console.error(`Failed to send notification to token: ${token}`, error); + // Check for specific error indicating an invalid token + if (error.code === 'messaging/registration-token-not-registered') { + // Remove the invalid token from the database + await User.updateOne( + { fcmIds: token }, // Ensure you're targeting the right user with the invalid token + { $pull: { fcmIds: token } } // Remove the invalid token + ); + console.log(`Removed invalid token: ${token}`); + } } }); @@ -2313,71 +2496,90 @@ const notificationSentStatus = { criticallyHighWater: false, }; -const checkWaterLevelsAndNotify = async (customerId, tankName, tankLocation, fcmTokens) => { - try { - // Fetch the tank details from the database - const tank = await Tank.findOne({ customerId, tankName, tankLocation }); +let waterLevelCheckInterval; // To hold the interval ID - if (!tank) { - console.error(`Tank not found: ${tankName} at location ${tankLocation}`); - return; - } +const checkWaterLevel = async (customerId, motorId, fcmToken, receiverTank) => { + const currentWaterLevel = parseInt(receiverTank.waterlevel, 10); + const tankCapacity = parseInt(receiverTank.capacity.replace(/,/g, ''), 10); + const currentWaterPercentage = (currentWaterLevel / tankCapacity) * 100; - // Extract the current water level and capacity - const currentWaterLevel = parseInt(tank.waterlevel, 10); - const capacity = parseInt(tank.capacity.replace(/,/g, ''), 10); - - // Calculate the water level percentage - const waterLevelPercentage = (currentWaterLevel / capacity) * 100; - - // Thresholds for notifications - const thresholds = { - criticallyLow: 10, - veryLow: 20, - low: 30, - high: 70, - veryHigh: 80, - criticallyHigh: 85, - }; + // Check for low water levels + if (currentWaterPercentage <= 20 && !notificationSentStatus.lowWater) { + eventEmitter.emit('sendLowWaterNotification', fcmToken, `Water level has dropped below 20%.`); + notificationSentStatus.lowWater = true; + } - // Check water levels and send notifications - if (waterLevelPercentage <= thresholds.criticallyLow && !notificationSentStatus.criticallyLowWater) { - eventEmitter.emit('sendCriticalLowWaterNotification', fcmTokens, tank); - notificationSentStatus.criticallyLowWater = true; - await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCritical: true } }); - } else if (waterLevelPercentage <= thresholds.veryLow && !notificationSentStatus.veryLowWater) { - eventEmitter.emit('sendVeryLowWaterNotification', fcmTokens, tank); - notificationSentStatus.veryLowWater = true; - await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryLow: true } }); - } else if (waterLevelPercentage <= thresholds.low && !notificationSentStatus.lowWater) { - eventEmitter.emit('sendLowWaterNotification', fcmTokens, tank); - notificationSentStatus.lowWater = true; - await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentLow: true } }); - } - // if (waterLevelPercentage <= thresholds.criticallyLow) { - // eventEmitter.emit('sendCriticalLowWaterNotification', fcmTokens, tank); - // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCritical: true } }); - // } else if (waterLevelPercentage <= thresholds.veryLow) { - // eventEmitter.emit('sendVeryLowWaterNotification', fcmTokens, tank); - // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryLow: true } }); - // } else if (waterLevelPercentage <= thresholds.low) { - // eventEmitter.emit('sendLowWaterNotification', fcmTokens, tank); - // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentLow: true } }); - // } - // else if (waterLevelPercentage >= thresholds.criticallyHigh) { - // eventEmitter.emit('sendCriticalHighWaterNotification', fcmTokens, tank); - // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCriticalHigh: true } }); - // } else if (waterLevelPercentage >= thresholds.veryHigh) { - // eventEmitter.emit('sendVeryHighWaterNotification', fcmTokens, tank); - // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryHigh: true } }); - // } else if (waterLevelPercentage >= thresholds.high) { - // eventEmitter.emit('sendHighWaterNotification', fcmTokens, tank); - // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentHigh: true } }); - // } - } catch (error) { - console.error(`Error checking water levels for tank ${tankName}:`, error); + // Check for critically low water levels + if (currentWaterPercentage <= 10 && !notificationSentStatus.criticallyLowWater) { + eventEmitter.emit('sendCriticalLowWaterNotification', fcmToken, `Water level has dropped below 10%.`); + notificationSentStatus.criticallyLowWater = true; } }; +// const checkWaterLevelsAndNotify = async (customerId, tankName, tankLocation, fcmTokens) => { +// try { +// // Fetch the tank details from the database +// const tank = await Tank.findOne({ customerId, tankName, tankLocation }); + +// if (!tank) { +// console.error(`Tank not found: ${tankName} at location ${tankLocation}`); +// return; +// } + +// // Extract the current water level and capacity +// const currentWaterLevel = parseInt(tank.waterlevel, 10); +// const capacity = parseInt(tank.capacity.replace(/,/g, ''), 10); + +// // Calculate the water level percentage +// const waterLevelPercentage = (currentWaterLevel / capacity) * 100; + +// // Thresholds for notifications +// const thresholds = { +// criticallyLow: 10, +// veryLow: 20, +// low: 30, +// high: 70, +// veryHigh: 80, +// criticallyHigh: 85, +// }; + +// // Check water levels and send notifications +// if (waterLevelPercentage <= thresholds.criticallyLow && !notificationSentStatus.criticallyLowWater) { +// eventEmitter.emit('sendCriticalLowWaterNotification', fcmTokens, tank); +// notificationSentStatus.criticallyLowWater = true; +// await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCritical: true } }); +// } else if (waterLevelPercentage <= thresholds.veryLow && !notificationSentStatus.veryLowWater) { +// eventEmitter.emit('sendVeryLowWaterNotification', fcmTokens, tank); +// notificationSentStatus.veryLowWater = true; +// await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryLow: true } }); +// } else if (waterLevelPercentage <= thresholds.low && !notificationSentStatus.lowWater) { +// eventEmitter.emit('sendLowWaterNotification', fcmTokens, tank); +// notificationSentStatus.lowWater = true; +// await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentLow: true } }); +// } +// // if (waterLevelPercentage <= thresholds.criticallyLow) { +// // eventEmitter.emit('sendCriticalLowWaterNotification', fcmTokens, tank); +// // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCritical: true } }); +// // } else if (waterLevelPercentage <= thresholds.veryLow) { +// // eventEmitter.emit('sendVeryLowWaterNotification', fcmTokens, tank); +// // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryLow: true } }); +// // } else if (waterLevelPercentage <= thresholds.low) { +// // eventEmitter.emit('sendLowWaterNotification', fcmTokens, tank); +// // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentLow: true } }); +// // } +// // else if (waterLevelPercentage >= thresholds.criticallyHigh) { +// // eventEmitter.emit('sendCriticalHighWaterNotification', fcmTokens, tank); +// // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCriticalHigh: true } }); +// // } else if (waterLevelPercentage >= thresholds.veryHigh) { +// // eventEmitter.emit('sendVeryHighWaterNotification', fcmTokens, tank); +// // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryHigh: true } }); +// // } else if (waterLevelPercentage >= thresholds.high) { +// // eventEmitter.emit('sendHighWaterNotification', fcmTokens, tank); +// // await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentHigh: true } }); +// // } +// } catch (error) { +// console.error(`Error checking water levels for tank ${tankName}:`, error); +// } +// }; const monitorWaterLevels = async () => { @@ -2479,7 +2681,7 @@ exports.motorAction = async (req, reply) => { ? `${req.body.manual_threshold_time} minutes` : `${req.body.manual_threshold_litres} litres`; - await checkWaterLevelsAndNotify(customerId, tankName, receiverTank.tankLocation, fcmToken); + // await checkWaterLevelsAndNotify(customerId, tankName, receiverTank.tankLocation, fcmToken); if (!notificationSentStatus.motorStart) { eventEmitter.emit( @@ -2494,6 +2696,12 @@ exports.motorAction = async (req, reply) => { ); notificationSentStatus.motorStart = true; // Set flag to true to prevent duplicate notifications + } + // Start checking water level every 30 minutes + if (!waterLevelCheckInterval) { + waterLevelCheckInterval = setInterval(async () => { + await checkWaterLevel(customerId, motorId, fcmToken, receiverTank); + }, 30 * 60 * 1000); // 30 minutes } await Tank.updateOne( { customerId, "connections.inputConnections.motor_id": motorId }, @@ -2507,30 +2715,8 @@ exports.motorAction = async (req, reply) => { } else if (action === "stop") { motorStopStatus = "1"; // If action is stop, set stop status to "1" - - - await checkWaterLevelsAndNotify(customerId, tankName, receiverTank.tankLocation, fcmToken); - - // eventEmitter.emit( - // "motorStop", - // fcmToken, - // // motorId, - // // currentWaterLevel, - // // blockName, - // tankName, - // stopTime, - // motorOnType - // ); - if (!notificationSentStatus.motorStop) { - // eventEmitter.emit( - // "motorStop", - // fcmToken, - // tankName, - // stopTime, - // "APP" - // ); // Emit motorStop event const totalWaterPumped = await calculateTotalPumpedWater(customerId, motorId, start_instance_id); // A function to calculate total water pumped @@ -2554,7 +2740,11 @@ exports.motorAction = async (req, reply) => { "connections.inputConnections.$.motor_on_type": motorOnType } } ); - + // Clear the interval when the motor is stopped + if (waterLevelCheckInterval) { + clearInterval(waterLevelCheckInterval); + waterLevelCheckInterval = null; // Reset the interval ID + } } else { throw new Error("Invalid action provided."); } @@ -2695,7 +2885,7 @@ exports.motorAction = async (req, reply) => { // clearInterval(motorIntervals[motorId]); // Clear interval // delete motorIntervals[motorId]; - await checkWaterLevelsAndNotify(customerId, tankName, supplierTank.tankLocation, fcmToken); + // await checkWaterLevelsAndNotify(customerId, tankName, supplierTank.tankLocation, fcmToken); // if (currentWaterPercentage >= highWaterThreshold && !notificationSentStatus.highWater) { // eventEmitter.emit('sendHighWaterNotification', fcmToken, `Water level has reached high levels.`); // notificationSentStatus.highWater = true; // Set flag to true to prevent duplicate notifications @@ -5237,6 +5427,7 @@ exports.getBlockData = async (req, reply) => { const mqtt = require('mqtt'); +const { setMaxIdleHTTPParsers } = require('http'); const client = mqtt.connect('mqtt://35.207.198.4:1883'); // Connect to MQTT broker client.on('connect', () => { @@ -5353,17 +5544,43 @@ client.on('message', async (topic, message) => { inputConnection.motor_on_type = "forced_manual"; inputConnection.startTime = currentTime; // Emit motor start notification with tankName - eventEmitter.emit( - "sendMotorStartNotification", - fcmToken, // FCM tokens - hw_Id, // Motor ID - inputConnection.water_level || 0, // Water level - motorTank.blockName || "N/A", // Block name - tankName, // Tank name - inputConnection.motor_on_type, // Motor on type - "threshold", // Stop criteria - manual_threshold_time // Threshold time in mins - ); + // eventEmitter.emit( + // "sendMotorStartNotification", + // fcmToken, // FCM tokens + // hw_Id, // Motor ID + // inputConnection.water_level || 0, // Water level + // motorTank.blockName || "N/A", // Block name + // tankName, // Tank name + // inputConnection.motor_on_type, // Motor on type + // "threshold", // Stop criteria + // manual_threshold_time // Threshold time in mins + // ); + + // Define logic to determine stopCriteria + let stopCriteria = ""; + let highThreshold = 90; // Example high threshold value + + let stopConditionMessage = ""; + if (stopCriteria === "manual") { + stopConditionMessage = `Will stop at Manually \n`; + } else if (stopCriteria === "highThreshold") { + stopConditionMessage = `🚨 Pump will stop when the water level reaches the high threshold of ${highThreshold}%.\n`; + } + + // Emit the event + try { + eventEmitter.emit("sendMotorStartNotification", + fcmToken, + motorTank.blockName || "N/A", + motorTank.tankName, + "Forced Manual", + stopCriteria, + motorTank.typeOfWater || "Drinking Water", + highThreshold + ); + } catch (error) { + console.error('Error emitting motor start notification:', error); + } } @@ -5371,18 +5588,20 @@ client.on('message', async (topic, message) => { inputConnection.motor_stop_status = "1"; // Emit motor stop notification with tankName - eventEmitter.emit( - "sendMotorStopNotification", - fcmToken, // FCM tokens - hw_Id, // Motor ID - inputConnection.water_level || 0, // Water level - motorTank.blockName || "N/A", // Block name - tankName, // Tank name - inputConnection.motor_on_type // Motor on type - ); + try { + eventEmitter.emit("sendMotorStopNotification", + fcmToken, + motorTank.blockName || "N/A", + motorTank.tankName, + "Forced Manual", + motorTank.typeOfWater || "Drinking Water" + ); + } catch (error) { + console.error('Error emitting motor stop notification:', error); + } } - await motorTank.save(); // Save the updated tank + await motorTank.save(); } console.log('Data processed successfully for hardwareId:', hw_Id); // Updated variable name @@ -5629,13 +5848,160 @@ console.log("this is for testing autopush,line located in tankscontroller") +// const calculateDailyConsumptionAndNotify = async () => { +// try { +// const today = moment().startOf("day"); +// const yesterday = moment(today).subtract(1, "days"); + +// // Fetch all active users +// const activeUsers = await User.find({ }); + +// for (const user of activeUsers) { +// const { customerId, fcmIds } = user; + +// // Fetch daily consumption for the customer +// const consumptions = await TankConsumptionOriginalSchema.find({ +// customerId, +// time: { +// $gte: yesterday.format("DD-MMM-YYYY - HH:mm"), +// $lt: today.format("DD-MMM-YYYY - HH:mm"), +// }, +// }); + +// // Calculate total consumption +// const totalConsumption = consumptions.reduce((total, record) => { +// return total + parseInt(record.consumption, 10); +// }, 0); + +// // Prepare tank-wise consumption details +// const tankDetails = consumptions.map((record) => ({ +// tankName: record.tankName, +// consumption: record.consumption, +// })); + +// // Send notification +// const notificationTitle = "Daily Water Consumption Report"; +// const notificationBody = ` +// Total Consumption: ${totalConsumption} liters +// Tank Details: ${tankDetails +// .map((tank) => `${tank.tankName}: ${tank.consumption} liters`) +// .join(", ")} +// `; + +// if (fcmIds && fcmIds.length > 0) { +// await sendNotification(fcmIds, notificationTitle, notificationBody); +// } +// } + +// console.log("Daily consumption notifications sent successfully."); +// } catch (err) { +// console.error("Error sending daily consumption notifications:", err); +// } +// }; + + +// cron.schedule("0 11:57 * * *", async () => { +// console.log("Starting daily consumption notification task..."); +// await calculateDailyConsumptionAndNotify(); +// }); + +// cron.schedule( +// "0 9 * * *", +// async () => { +// console.log("Starting daily consumption notification task..."); +// await calculateDailyConsumptionAndNotify(); +// }, +// { +// timezone: "Asia/Kolkata", // Specify the timezone +// } +// ); + +// const calculateDailyConsumptionAndNotify = async () => { +// try { +// const today = moment().startOf("day"); +// const yesterday = moment(today).subtract(1, "days"); + +// // Fetch all active users +// const activeUsers = await User.find({}); + +// for (const user of activeUsers) { +// const { customerId, fcmIds } = user; + +// // Fetch daily consumption for the customer +// const consumptions = await TankConsumptionOriginalSchema.find({ +// customerId, +// time: { +// $gte: yesterday.format("DD-MMM-YYYY - HH:mm"), +// $lt: today.format("DD-MMM-YYYY - HH:mm"), +// }, +// }); + +// // Calculate total consumption by type of water and the water level percentage +// const consumptionSummary = consumptions.reduce((acc, record) => { +// const typeOfWater = record.typeOfWater; // Assuming this field exists +// const consumption = parseInt(record.consumption, 10); +// const waterLevel = parseInt(record.waterLevel, 10); // Assuming waterLevel is in percentage + +// if (!acc[typeOfWater]) { +// acc[typeOfWater] = { +// totalConsumption: 0, +// tankDetails: [], +// totalWaterLevel: 0, +// count: 0, +// }; +// } + +// acc[typeOfWater].totalConsumption += consumption; +// acc[typeOfWater].totalWaterLevel += waterLevel; +// acc[typeOfWater].count += 1; +// acc[typeOfWater].tankDetails.push({ +// tankName: record.tankName, +// consumption, +// waterLevel, +// }); + +// return acc; +// }, {}); + +// // Prepare notification body +// let notificationBody = "Daily Water Consumption Report:\n"; +// for (const type in consumptionSummary) { +// const { totalConsumption, tankDetails, totalWaterLevel, count } = consumptionSummary[type]; +// const averageWaterLevel = (totalWaterLevel / count).toFixed(2); // Calculate average water level +// console.log("averageWaterLevel",averageWaterLevel) +// console.log("totalConsumption",totalConsumption) + +// notificationBody += ` +// Type of Water: ${type} +// Total Consumption: ${totalConsumption} liters +// Average Water Level: ${averageWaterLevel}% +// `; +// console.log("noti---" ,notificationBody += ` +// Type of Water: ${type} +// Total Consumption: ${totalConsumption} liters +// Average Water Level: ${averageWaterLevel}% +// `) +// } + +// if (fcmIds && fcmIds.length > 0) { +// await sendNotification(fcmIds, "Daily Water Consumption Report", notificationBody); +// } +// } + +// console.log("Daily consumption notifications sent successfully."); +// } catch (err) { +// console.error("Error sending daily consumption notifications:", err); +// } +// }; + + const calculateDailyConsumptionAndNotify = async () => { try { const today = moment().startOf("day"); const yesterday = moment(today).subtract(1, "days"); // Fetch all active users - const activeUsers = await User.find({ }); + const activeUsers = await User.find({}); for (const user of activeUsers) { const { customerId, fcmIds } = user; @@ -5649,28 +6015,46 @@ const calculateDailyConsumptionAndNotify = async () => { }, }); - // Calculate total consumption - const totalConsumption = consumptions.reduce((total, record) => { - return total + parseInt(record.consumption, 10); - }, 0); + // Calculate total consumption and capacities based on water type + let totalBoreConsumption = 0; + let totalDrinkingConsumption = 0; + let totalBoreCapacity = 0; + let totalDrinkingCapacity = 0; + + for (const record of consumptions) { + const typeOfWater = record.typeOfWater; // Assuming this field exists + const consumption = parseInt(record.consumption, 10); + const capacity = parseInt(record.capacity, 10); // Assuming capacity field exists + + if (typeOfWater === "bore" || typeOfWater === "Bore Water") { + totalBoreConsumption += consumption; + totalBoreCapacity += capacity; + } else if (typeOfWater === "drinking" || typeOfWater === "Drinking Water") { + totalDrinkingConsumption += consumption; + totalDrinkingCapacity += capacity; + } + } - // Prepare tank-wise consumption details - const tankDetails = consumptions.map((record) => ({ - tankName: record.tankName, - consumption: record.consumption, - })); + // Calculate percentages + const boreConsumptionPercentage = totalBoreCapacity + ? ((totalBoreConsumption / totalBoreCapacity) * 100).toFixed(2) + : 0; + + const drinkingConsumptionPercentage = totalDrinkingCapacity + ? ((totalDrinkingConsumption / totalDrinkingCapacity) * 100).toFixed(2) + : 0; - // Send notification - const notificationTitle = "Daily Water Consumption Report"; - const notificationBody = ` - Total Consumption: ${totalConsumption} liters - Tank Details: ${tankDetails - .map((tank) => `${tank.tankName}: ${tank.consumption} liters`) - .join(", ")} - `; + // Prepare notification body + const reportDate = yesterday.format("DD-MMM-YYYY"); + let notificationBody = `Daily Water Consumption Report for ${reportDate}:\n`; + notificationBody += `Total Bore Consumption: ${totalBoreConsumption} liters\n`; + notificationBody += `Bore Water Consumption Percentage: ${boreConsumptionPercentage}%\n`; + notificationBody += `Total Drinking Consumption: ${totalDrinkingConsumption} liters\n`; + notificationBody += `Drinking Water Consumption Percentage: ${drinkingConsumptionPercentage}%\n`; + // Send notification if FCM IDs are present if (fcmIds && fcmIds.length > 0) { - await sendNotification(fcmIds, notificationTitle, notificationBody); + await sendNotification(fcmIds, "Daily Water Consumption Report", notificationBody); } } @@ -5680,12 +6064,7 @@ const calculateDailyConsumptionAndNotify = async () => { } }; - -// cron.schedule("0 11:57 * * *", async () => { -// console.log("Starting daily consumption notification task..."); -// await calculateDailyConsumptionAndNotify(); -// }); - +// Schedule the cron job to run daily at 9 AM cron.schedule( "0 9 * * *", async () => { @@ -5696,3 +6075,92 @@ cron.schedule( timezone: "Asia/Kolkata", // Specify the timezone } ); + + +const calculateConsumptionAndNotify = async () => { + try { + const now = moment(); // Current time + const sixHoursAgo = moment(now).subtract(6, 'hours').startOf('hour'); // 6 hours ago + + // Fetch all active users + const activeUsers = await User.find({}); + + for (const user of activeUsers) { + const { customerId, fcmIds } = user; + + // Fetch consumption records for the last 6 hours + const consumptions = await TankConsumptionOriginalSchema.find({ + customerId, + time: { + $gte: sixHoursAgo.format("DD-MMM-YYYY - HH:mm"), + $lt: now.format("DD-MMM-YYYY - HH:mm"), + }, + }); + + // Prepare notification body + let notificationBody = `Water Consumption Report (From ${sixHoursAgo.format( + "hh:mm A" + )} to ${now.format("hh:mm A")}):\n`; + const tankDetails = {}; + + // Aggregate consumption data by tank + for (const record of consumptions) { + const tankName = record.tankName; // Assuming this field exists + const tankLocation = record.tankLocation; // Assuming this field exists + const consumption = parseInt(record.consumption, 10); // Liters consumed + const typeOfWater = record.typeOfWater; // Type of water (e.g., bore, drinking) + const tankCapacity = parseInt(record.capacity, 10); // Tank capacity in liters + + if (!tankDetails[tankName]) { + tankDetails[tankName] = { + tankLocation, + totalConsumption: 0, + typeOfWater, + tankCapacity, + }; + } + tankDetails[tankName].totalConsumption += consumption; + } + + // Format tank details for the notification + for (const tankName in tankDetails) { + const { + tankLocation, + totalConsumption, + typeOfWater, + tankCapacity, + } = tankDetails[tankName]; + const consumptionPercentage = tankCapacity + ? ((totalConsumption / tankCapacity) * 100).toFixed(2) + : 0; + + notificationBody += + `Tank Name: ${tankName} \n`+ + `Location: ${tankLocation} \n`+ + `Total Consumption: ${totalConsumption} liters ${consumptionPercentage}% \n`+ + `Type of Water: ${typeOfWater}`; + } + + // Send notification if FCM IDs are present + if (fcmIds && fcmIds.length > 0) { + await sendNotification(fcmIds, "Water Consumption Report", notificationBody); + } + } + + console.log("Consumption notifications sent successfully."); + } catch (err) { + console.error("Error sending consumption notifications:", err); + } +}; + +// Schedule notifications at 6 AM, 12 PM, 6 PM, and 12 AM +cron.schedule( + "0 6,12,18,0 * * *", // Cron expression for the required times + async () => { + console.log("Starting scheduled consumption notification task..."); + await calculateConsumptionAndNotify(); + }, + { + timezone: "Asia/Kolkata", // Specify the timezone + } +);