ashok 9 months ago
commit bef726d783

@ -160,23 +160,53 @@ exports.updateTanksInfo = async (req, reply) => {
} }
}; };
//delete selected tank
exports.deleteTanksInfo = async (req, reply) => { exports.deleteTanksInfo = async (req, reply) => {
try { try {
const customerId = req.params.customerId; const { customerId } = req.params;
const { tankName } = req.query;
const tankName = req.query.tankName;
const tankLocation = req.body.tankLocation.toLowerCase(); const tankLocation = req.body.tankLocation.toLowerCase();
const tank = await Tank.findOneAndDelete({ tankName: tankName,customerId:customerId,tankLocation:tankLocation }); if (!tankName || !tankLocation) {
return reply.code(400).send({ message: "Tank name and location are required" });
}
reply.send({ status_code: 200, data: tank}); // Convert tankLocation to lowercase (for case-insensitive match)
// return tank; const normalizedTankLocation = tankLocation.toLowerCase();
} catch (err) {
throw boom.boomify(err); // Find and delete the main tank
const deletedTank = await Tank.findOneAndDelete({
customerId,
tankName,
tankLocation: normalizedTankLocation
});
if (!deletedTank) {
return reply.code(404).send({ message: "Tank not found" });
}
// Remove the deleted tank from inputConnections and outputConnections in all other tanks
await Tank.updateMany(
{ customerId },
{
$pull: {
"connections.inputConnections": { inputConnections: tankName },
"connections.outputConnections": { outputConnections: tankName }
}
}
);
return reply.send({ message: "Tank deleted successfully" });
} catch (error) {
console.error("Error deleting tank:", error);
return reply.code(500).send({ message: "Internal Server Error" });
} }
}; };
exports.getConnectionsInfoOfParticularTank = async (req, reply) => { exports.getConnectionsInfoOfParticularTank = async (req, reply) => {
try { try {
const customerId = req.params.customerId; const customerId = req.params.customerId;
@ -349,6 +379,7 @@ exports.getTanksofParticularInstaller = async (req, reply) => {
// throw boom.boomify(err); // throw boom.boomify(err);
// } // }
//}; //};
// const boom = require("@hapi/boom"); // Assuming you are using boom for error handling
@ -357,45 +388,49 @@ exports.getTankmotordata = async (req, reply) => {
const { startDate, stopDate } = req.body; const { startDate, stopDate } = req.body;
const { customerId } = req.params; const { customerId } = req.params;
// Parse the input startDate and stopDate using the desired format // Validate and format the input dates
// const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate(); if (!moment(startDate, "DD-MMM-YYYY - HH:mm", true).isValid() || !moment(stopDate, "DD-MMM-YYYY - HH:mm", true).isValid()) {
// const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate(); return reply.send({ status_code: 400, message: "Invalid date format" });
// console.log(start,"start",end,"end") }
// Check if the parsed dates are valid
// Convert the dates to the correct format for storage or querying (still in UTC) // Convert input dates to ISO 8601 format for Date comparison
// This gives a native JS Date object for querying const startISODate = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
const stopISODate = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();
// Fetch the name from the User collection based on customerId, only from profile // Convert input dates to string format for string-based comparison
const user = await User.findOne({ customerId }) const startStringDate = moment(startDate, "DD-MMM-YYYY - HH:mm").format("DD-MMM-YYYY - HH:mm");
.select("username"); const stopStringDate = moment(stopDate, "DD-MMM-YYYY - HH:mm").format("DD-MMM-YYYY - HH:mm");
// Fetch the username based on customerId
const user = await User.findOne({ customerId }).select("username");
if (user) { if (user) {
// Get the full name (combine firstName and lastName if available) const userName = user.username || "N/A";
const userName = user.username
? `${user.username}` // Query the MotorData collection
: "N/A"; // Fallback if no name is found const motorDataDocs = await MotorData.find({
customerId,
// Construct the query object for motor data based on customerId $or: [
const motorQuery = { customerId }; {
startTime: { $gte: startISODate, $lte: stopISODate }, // Date-based comparison
// Fetch motor data for the customerId within the time range },
const motorDataDocs = await MotorData.find(motorQuery) {
.where("startTime") startTime: { $gte: startStringDate, $lte: stopStringDate }, // String-based comparison
.gte(startDate) // Greater than or equal to startDate },
.lte(stopDate) // Less than or equal to stopDate ],
.exec(); }).exec();
reply.send({ reply.send({
status_code: 200, status_code: 200,
data: motorDataDocs, data: motorDataDocs,
count: motorDataDocs.length, count: motorDataDocs.length,
customerName: userName, // Add the username to the response customerName: userName,
}); });
} else { } else {
reply.send({ status_code: 404, message: "User not found" }); reply.send({ status_code: 404, message: "User not found" });
} }
} catch (err) { } catch (err) {
console.error("Error in getTankmotordata:", err);
throw boom.boomify(err); throw boom.boomify(err);
} }
}; };
@ -2678,7 +2713,7 @@ const monitorWaterLevels = async () => {
const tankLocation = tank.tankLocation; // Assuming tank has a 'location' field const tankLocation = tank.tankLocation; // Assuming tank has a 'location' field
// Call the function to check water levels and send notifications // Call the function to check water levels and send notifications
await checkWaterLevelsAndNotify(customerId, tankName, tankLocation, fcmTokens); //await checkWaterLevelsAndNotify(customerId, tankName, tankLocation, fcmTokens);
} else { } else {
//console.log(`No FCM tokens found for customerId ${tank.customerId}`); //console.log(`No FCM tokens found for customerId ${tank.customerId}`);
} }
@ -2938,11 +2973,11 @@ exports.motorAction = async (req, reply) => {
console.log(thresholdTime,"thresholdTime") console.log(thresholdTime,"thresholdTime")
console.log("motor stopping because it entered this condition") console.log("motor stopping because it entered this condition")
// Emit the threshold time notification // Emit the threshold time notification
eventEmitter.emit( // eventEmitter.emit(
"sendThresholdTimeNotification", // "sendThresholdTimeNotification",
fcmToken, // fcmToken,
`Motor has reached its time threshold of ${req.body.manual_threshold_time} minutes and will stop.` // `Motor has reached its time threshold of ${req.body.manual_threshold_time} minutes and will stop.`
); // );
await Tank.updateOne( await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId }, { customerId, "connections.inputConnections.motor_id": motorId },
@ -5665,17 +5700,17 @@ client.on('message', async (topic, message) => {
inputConnection.motor_on_type = "forced_manual"; inputConnection.motor_on_type = "forced_manual";
inputConnection.startTime = currentTime; inputConnection.startTime = currentTime;
// Emit motor start notification with tankName // Emit motor start notification with tankName
eventEmitter.emit( // eventEmitter.emit(
"sendMotorStartNotification", // "sendMotorStartNotification",
fcmToken, // FCM tokens // fcmToken, // FCM tokens
hw_Id, // Motor ID // hw_Id, // Motor ID
inputConnection.water_level || 0, // Water level // inputConnection.water_level || 0, // Water level
motorTank.blockName || "N/A", // Block name // motorTank.blockName || "N/A", // Block name
tankName, // Tank name // tankName, // Tank name
inputConnection.motor_on_type, // Motor on type // inputConnection.motor_on_type, // Motor on type
"threshold", // Stop criteria // "threshold", // Stop criteria
manual_threshold_time // Threshold time in mins // manual_threshold_time // Threshold time in mins
); // );
} }
@ -5683,15 +5718,15 @@ client.on('message', async (topic, message) => {
inputConnection.motor_stop_status = "1"; inputConnection.motor_stop_status = "1";
// Emit motor stop notification with tankName // Emit motor stop notification with tankName
eventEmitter.emit( // eventEmitter.emit(
"sendMotorStopNotification", // "sendMotorStopNotification",
fcmToken, // FCM tokens // fcmToken, // FCM tokens
hw_Id, // Motor ID // hw_Id, // Motor ID
inputConnection.water_level || 0, // Water level // inputConnection.water_level || 0, // Water level
motorTank.blockName || "N/A", // Block name // motorTank.blockName || "N/A", // Block name
tankName, // Tank name // tankName, // Tank name
inputConnection.motor_on_type // Motor on type // inputConnection.motor_on_type // Motor on type
); // );
} }
await motorTank.save(); // Save the updated tank await motorTank.save(); // Save the updated tank
@ -6246,14 +6281,193 @@ const calculateConsumptionAndNotify = async () => {
} }
}; };
const calculateWaterLevelAndNotify = async () => {
try {
const now = moment();
const sixHoursAgo = moment().subtract(6, "hours");
console.log(`Calculating water level between ${sixHoursAgo.format("HH:mm A")} and ${now.format("HH:mm A")}`);
const tanks = await Tank.find({});
for (const tank of tanks) {
const {
customerId,
tankName,
tankLocation,
typeOfWater,
capacity,
waterlevel,
waterlevel_at_midnight,
} = tank;
// ✅ Fix: Remove commas before parsing numbers
const tankCapacity = parseFloat(capacity.replace(/,/g, '')) || 0;
const currentWaterLevel = parseFloat(waterlevel.replace(/,/g, '')) || 0;
const midnightWaterLevel = parseFloat(waterlevel_at_midnight.replace(/,/g, '')) || 0;
if (tankCapacity === 0) {
console.log(`Skipping tank ${tankName} due to zero capacity`);
continue;
}
const currentWaterLevelPercentage = ((currentWaterLevel / tankCapacity) * 100).toFixed(2);
const waterUsedSinceMidnight = midnightWaterLevel - currentWaterLevel;
const waterUsedPercentageSinceMidnight = ((waterUsedSinceMidnight / tankCapacity) * 100).toFixed(2);
const user = await User.findOne({ customerId });
if (!user || !user.fcmIds || user.fcmIds.length === 0) {
console.log(`No FCM tokens for customer: ${customerId}`);
continue;
}
let notificationBody =
`🛢️ Tank Name: ${tankName}\n` +
`🏢 Location: ${tankLocation}\n` +
`💧 Type of Water: ${typeOfWater}\n` +
`Current Water Level: ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n`;
await sendNotification(user.fcmIds, "Water Level Update", notificationBody);
}
console.log("Water level notifications sent successfully.");
} catch (err) {
console.error("Error in water level calculation:", err);
}
};
// Schedule notifications at 6 AM, 12 PM, 6 PM, and 12 AM // Schedule notifications at 6 AM, 12 PM, 6 PM, and 12 AM
cron.schedule( cron.schedule(
"0 6,12,18,0 * * *", // Cron expression for the required times "0 6,12,18,0 * * *", // Cron expression for the required times
async () => { async () => {
console.log("Starting scheduled consumption notification task..."); console.log("Starting scheduled consumption notification task...");
await calculateConsumptionAndNotify(); //await calculateConsumptionAndNotify();
await calculateWaterLevelAndNotify();
}, },
{ {
timezone: "Asia/Kolkata", // Specify the timezone timezone: "Asia/Kolkata", // Specify the timezone
} }
); );
// const updateStopTimeFormat = async () => {
// try {
// // Find records where stopTime is null or not in the required format
// const motorDataDocs = await MotorData.find();
// for (const doc of motorDataDocs) {
// // Parse and validate startTime
// const startTime = moment(doc.startTime, "DD-MMM-YYYY - HH:mm", true);
// if (!startTime.isValid()) {
// console.log(`Invalid startTime for record ID: ${doc._id}`);
// continue;
// }
// // Format startTime if it's not already formatted
// const formattedStartTime = startTime.format("DD-MMM-YYYY - HH:mm");
// // Check if stopTime is valid or calculate it
// let formattedStopTime = null;
// const stopTime = moment(doc.stopTime, "DD-MMM-YYYY - HH:mm", true);
// if (!stopTime.isValid()) {
// // Calculate stopTime by adding 30 minutes to startTime
// formattedStopTime = startTime.clone().add(30, "minutes").format("DD-MMM-YYYY - HH:mm");
// } else {
// // Format the existing stopTime
// formattedStopTime = stopTime.format("DD-MMM-YYYY - HH:mm");
// }
// // Update the document if startTime or stopTime is not correctly formatted
// if (doc.startTime !== formattedStartTime || doc.stopTime !== formattedStopTime) {
// await MotorData.updateOne(
// { _id: doc._id },
// {
// $set: {
// startTime: formattedStartTime,
// stopTime: formattedStopTime,
// },
// }
// );
// console.log(`Updated record ID: ${doc._id}`);
// }
// }
// console.log("StopTime format update completed.");
// } catch (err) {
// console.error("Error updating stopTime format:", err);
// }
// };
// // Call the function to update stopTime
// updateStopTimeFormat();
exports.updatetankstatus = async (req, reply) => {
try {
const { customerId } = req.params;
const { tankName, tankLocation, status } = req.body;
if (!["active", "inactive"].includes(status)) {
return reply.code(400).send({ message: "Invalid status value" });
}
// Find the main tank
const mainTank = await Tank.findOneAndUpdate(
{ customerId, tankName, tankLocation },
{ $set: { status } },
{ new: true }
);
if (!mainTank) {
return reply.code(404).send({ message: "Tank not found" });
}
// Update status in related outputConnections tanks
await Tank.updateMany(
{
customerId,
"connections.outputConnections.outputConnections": tankName,
},
{ $set: { "connections.outputConnections.$.status": status } }
);
// Update status in related inputConnections tanks
await Tank.updateMany(
{
customerId,
"connections.inputConnections.inputConnections": tankName,
},
{ $set: { "connections.inputConnections.$.status": status } }
);
return reply.send({ message: "Tank status updated successfully" });
} catch (error) {
console.error("Error updating tank status:", error);
return reply.code(500).send({ message: "Internal Server Error" });
}
};
exports.listofactiveandinactivetankstatus = async (req, reply) => {
try {
const { customerId } = req.params;
const { status } = req.query;
if (!["active", "inactive"].includes(status)) {
return reply.code(400).send({ message: "Invalid status value" });
}
// Find tanks based on customerId and status
const tanks = await Tank.find({ customerId, status });
return reply.send({ tanks });
} catch (error) {
console.error("Error fetching tank list:", error);
return reply.code(500).send({ message: "Internal Server Error" });
}
};

@ -63,7 +63,7 @@ const tanksSchema = new mongoose.Schema({
notificationSentVeryHigh: { type: Boolean }, notificationSentVeryHigh: { type: Boolean },
notificationSentHigh: { type: Boolean }, notificationSentHigh: { type: Boolean },
all_motor_status: { type: Boolean }, all_motor_status: { type: Boolean },
status:{ type: String, default: "active" },
connections: { connections: {
source: { type: String }, source: { type: String },
@ -81,7 +81,7 @@ const tanksSchema = new mongoose.Schema({
water_level: { type: String, default: null }, water_level: { type: String, default: null },
manual_threshold_percentage: { type: String, default: "90" }, manual_threshold_percentage: { type: String, default: "90" },
manual_threshold_time: { type: String, default: null }, manual_threshold_time: { type: String, default: null },
status:{ type: String, default: "active" },
stop_threshold_time: { type: String, default: null }, stop_threshold_time: { type: String, default: null },
threshold_type: { type: String, default: "percentage" }, threshold_type: { type: String, default: "percentage" },
startTime: { type: String, default: null }, startTime: { type: String, default: null },
@ -103,7 +103,8 @@ const tanksSchema = new mongoose.Schema({
manual_threshold_percentage: { type: String, default: "90" }, manual_threshold_percentage: { type: String, default: "90" },
manual_threshold_time: { type: String, default: null }, manual_threshold_time: { type: String, default: null },
threshold_type: { type: String, default: "percentage" }, threshold_type: { type: String, default: "percentage" },
waterlevelPercentage: { type: String, default: null } waterlevelPercentage: { type: String, default: null } ,
status:{ type: String, default: "active" },
} }
], ],
inputWaterlevelPercentage: { type: String, default: null }, inputWaterlevelPercentage: { type: String, default: null },

@ -1231,6 +1231,70 @@ module.exports = function (fastify, opts, next) {
}); });
fastify.route({
method: "PUT",
url: "/api/updatetankstatus/:customerId",
schema: {
tags: ["Tank"],
summary: "This is for updating tank status to active or inactive",
params: {
required: ["customerId"],
type: "object",
properties: {
customerId: {
type: "string",
description: "customerId",
},
},
},
body: {
type: "object",
// required: ['phone'],
properties: {
tankName:{ type: "string" },
tankLocation:{type:"string"},
status:{type:"string"},
},
},
security: [
{
basicAuth: [],
},
],
},
//preHandler: fastify.auth([fastify.authenticate]),
handler: tanksController.updatetankstatus,
});
fastify.route({
method: "GET",
url: "/api/listofactiveandinactivetankstatus/:customerId",
schema: {
tags: ["Tank"],
summary: "Get list of active or inactive tanks",
params: {
required: ["customerId"],
type: "object",
properties: {
customerId: { type: "string", description: "Customer ID" },
},
},
querystring: {
type: "object",
properties: {
status: { type: "string", enum: ["active", "inactive"] },
},
},
security: [{ basicAuth: [] }],
},
handler: tanksController.listofactiveandinactivetankstatus,
});
next(); next();
} }

Loading…
Cancel
Save