ashok 9 months ago
commit bef726d783

@ -160,23 +160,53 @@ exports.updateTanksInfo = async (req, reply) => {
}
};
//delete selected tank
exports.deleteTanksInfo = async (req, reply) => {
try {
const customerId = req.params.customerId;
const tankName = req.query.tankName;
const { customerId } = req.params;
const { tankName } = req.query;
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});
// return tank;
} catch (err) {
throw boom.boomify(err);
// Convert tankLocation to lowercase (for case-insensitive match)
const normalizedTankLocation = tankLocation.toLowerCase();
// 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) => {
try {
const customerId = req.params.customerId;
@ -349,6 +379,7 @@ exports.getTanksofParticularInstaller = async (req, reply) => {
// 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 { customerId } = req.params;
// Parse the input startDate and stopDate using the desired format
// const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
// const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();
// console.log(start,"start",end,"end")
// Check if the parsed dates are valid
// Validate and format the input dates
if (!moment(startDate, "DD-MMM-YYYY - HH:mm", true).isValid() || !moment(stopDate, "DD-MMM-YYYY - HH:mm", true).isValid()) {
return reply.send({ status_code: 400, message: "Invalid date format" });
}
// Convert the dates to the correct format for storage or querying (still in UTC)
// This gives a native JS Date object for querying
// Convert input dates to ISO 8601 format for Date comparison
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
const user = await User.findOne({ customerId })
.select("username");
// Convert input dates to string format for string-based comparison
const startStringDate = moment(startDate, "DD-MMM-YYYY - HH:mm").format("DD-MMM-YYYY - HH:mm");
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) {
// Get the full name (combine firstName and lastName if available)
const userName = user.username
? `${user.username}`
: "N/A"; // Fallback if no name is found
// Construct the query object for motor data based on customerId
const motorQuery = { customerId };
// Fetch motor data for the customerId within the time range
const motorDataDocs = await MotorData.find(motorQuery)
.where("startTime")
.gte(startDate) // Greater than or equal to startDate
.lte(stopDate) // Less than or equal to stopDate
.exec();
const userName = user.username || "N/A";
// Query the MotorData collection
const motorDataDocs = await MotorData.find({
customerId,
$or: [
{
startTime: { $gte: startISODate, $lte: stopISODate }, // Date-based comparison
},
{
startTime: { $gte: startStringDate, $lte: stopStringDate }, // String-based comparison
},
],
}).exec();
reply.send({
status_code: 200,
data: motorDataDocs,
count: motorDataDocs.length,
customerName: userName, // Add the username to the response
customerName: userName,
});
} else {
reply.send({ status_code: 404, message: "User not found" });
}
} catch (err) {
console.error("Error in getTankmotordata:", err);
throw boom.boomify(err);
}
};
@ -2678,7 +2713,7 @@ const monitorWaterLevels = async () => {
const tankLocation = tank.tankLocation; // Assuming tank has a 'location' field
// Call the function to check water levels and send notifications
await checkWaterLevelsAndNotify(customerId, tankName, tankLocation, fcmTokens);
//await checkWaterLevelsAndNotify(customerId, tankName, tankLocation, fcmTokens);
} else {
//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("motor stopping because it entered this condition")
// Emit the threshold time notification
eventEmitter.emit(
"sendThresholdTimeNotification",
fcmToken,
`Motor has reached its time threshold of ${req.body.manual_threshold_time} minutes and will stop.`
);
// eventEmitter.emit(
// "sendThresholdTimeNotification",
// fcmToken,
// `Motor has reached its time threshold of ${req.body.manual_threshold_time} minutes and will stop.`
// );
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
@ -5665,17 +5700,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
// );
}
@ -5683,15 +5718,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
@ -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
cron.schedule(
"0 6,12,18,0 * * *", // Cron expression for the required times
async () => {
console.log("Starting scheduled consumption notification task...");
await calculateConsumptionAndNotify();
//await calculateConsumptionAndNotify();
await calculateWaterLevelAndNotify();
},
{
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 },
notificationSentHigh: { type: Boolean },
all_motor_status: { type: Boolean },
status:{ type: String, default: "active" },
connections: {
source: { type: String },
@ -81,7 +81,7 @@ const tanksSchema = new mongoose.Schema({
water_level: { type: String, default: null },
manual_threshold_percentage: { type: String, default: "90" },
manual_threshold_time: { type: String, default: null },
status:{ type: String, default: "active" },
stop_threshold_time: { type: String, default: null },
threshold_type: { type: String, default: "percentage" },
startTime: { type: String, default: null },
@ -103,7 +103,8 @@ const tanksSchema = new mongoose.Schema({
manual_threshold_percentage: { type: String, default: "90" },
manual_threshold_time: { type: String, default: null },
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 },

@ -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();
}

Loading…
Cancel
Save