You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7757 lines
292 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//const Tank = require("../models/tanks");
const { Tank, MotorData, IotData,MotorIot,TankWaterLevel,TankConsumptionSchema,TankConsumptionOriginalSchema,CustomerAutoPercentages } = require('../models/tanks')
const {User} = require("../models/User");
const boom = require("boom");
const fastify = require("fastify")({
logger: true,
});
// const tanksController = require("./tanksController")
const cron = require('node-cron');
const moment = require('moment');
const EventEmitter = require('events');
EventEmitter.defaultMaxListeners = 50; // Increase listener limit
const eventEmitter = new EventEmitter();
async function deleteOldRecords() {
const SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
const sevenDaysAgo = new Date(Date.now() - SEVEN_DAYS_IN_MILLISECONDS);
await MotorData.deleteMany({ startTime: { $lt: sevenDaysAgo } });
}
// exports.addTanks = async (req, reply) => {
// try {
// var customerId = req.params.customerId
// //const username = req.params.username;
// console.log(req.params);
// //const {username} = loginObject.user.username;
// //console.log(loginObject.user.username)
// // const userInfo = await User.findOne({ username: username.toString() });
// // const updateData = req.body;
// // console.log("This is the reply in the handler after the validations", reply);
// tankData = {
// customerId: customerId,
// hardwareId: req.body.hardwareId,
// tankName: req.body.tankName,
// blockName: req.body.blockName,
// capacity: req.body.capacity,
// typeOfWater: req.body.typeOfWater,
// tankLocation:req.body.tankLocation.toLowerCase(),
// };
// //console.log( req.body.tankLocation.toLowerCase())
// var tank_name = req.body.tankName
// var tankLocation = req.body.tankLocation.toLowerCase()
// var i_tank = await Tank.findOne({ tankName: tank_name,customerId:customerId,tankLocation:tankLocation})
// if(i_tank){
// throw new Error('tankname already exists');
// }
// else {
// var tank = new Tank(tankData);
// checkFormEncoding = isUserFormUrlEncoded(req);
// if (checkFormEncoding.isUserFormUrlEncoded) {
// usertobeInserted = checkFormEncoding.tank;
// console.log("thsi true url string");
// tank.customerId = usertobeInserted.customerId
// tank.hardwareId = usertobeInserted.hardwareId;
// tank.tankName = usertobeInserted.tankName;
// tank.blockName = usertobeInserted.blockName;
// tank.capacity = usertobeInserted.capacity;
// tank.typeOfWater = usertobeInserted.typeOfWater;
// tank.tankLocation = (usertobeInserted.tankLocation).toLowerCase();
// console.log((usertobeInserted.tankLocation).toLowerCase())
// }
// }
// const insertedTank = await tank.save();
// return insertedTank;
// } catch (err) {
// throw boom.boomify(err);
// }
// };
exports.addTanks = async (req, reply) => {
try {
const customerId = req.params.customerId;
const { hardwareId, tankhardwareId,tankName,tankLocation,need_sensor,blockName } = req.body;
const existingTank = await Tank.findOne({
customerId: customerId,
hardwareId: hardwareId,
tankhardwareId: tankhardwareId,
tankName:tankName,
tankLocation:tankLocation.toLowerCase(),
blockName:blockName
});
if (existingTank) {
throw new Error('The combination of hardwareId and tankhardwareId already exists.');
}
const tankData = {
// InstallerId:InstallerId,
customerId: customerId,
hardwareId: hardwareId,
tankhardwareId: tankhardwareId,
shape: req.body.shape,
tankName: req.body.tankName,
blockName: req.body.blockName,
capacity: req.body.capacity,
typeOfWater: req.body.typeOfWater,
tankLocation: req.body.tankLocation.toLowerCase(),
waterCapacityPerCm:req.body.waterCapacityPerCm,
height:req.body.height,
length:req.body.length,
width:req.body.width,
need_sensor:req.body.need_sensor
// ... other fields
};
const tank = new Tank(tankData);
const insertedTank = await tank.save();
return insertedTank;
} catch (err) {
throw boom.boomify(err);
}
};
//update selected tank
exports.updateTanksInfo = async (req, reply) => {
try {
const customerId = req.params.customerId;
const tankName = req.query.tankName;
const tank = req.body;
const { ...updateData } = tank;
console.log(tank)
const update = await Tank.findOneAndUpdate({customerId:customerId,tankName: tankName,tankLocation:req.body.tankLocation }, updateData, { new: true });
//console.log(update.username)
//return update;
reply.send({ status_code: 200, data: update });
}
catch (err) {
throw boom.boomify(err);
}
};
exports.deleteTanksInfo = async (req, reply) => {
try {
const { customerId } = req.params;
const { tankName } = req.query;
const tankLocation = req.body.tankLocation.toLowerCase();
if (!tankName || !tankLocation) {
return reply.code(400).send({ message: "Tank name and location are required" });
}
// 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;
const tankName = req.body.tankName;
const tankLocation = req.body.tankLocation.toLowerCase();
console.log(customerId, tankName, tankLocation);
// Find the specific tank
const mainTank = await Tank.findOne({
tankName: tankName,
customerId: customerId,
tankLocation: tankLocation
});
if (!mainTank) {
return reply.send({ status_code: 404, error: "Main tank not found" });
}
// Send the found tank within a list
reply.send({ status_code: 200, data: [mainTank] });
} catch (err) {
throw boom.boomify(err);
}
};
//get tanks data by passing username
exports.getTank = async (req, reply) => {
try {
await Tank.find({ customerId: req.query.customerId })
.exec()
.then((docs) => {
let totalSwitchCount = 0;
let totalSensorCount = 0;
const transformedDocs = docs.map((tank) => {
const inputConnections = tank.connections?.inputConnections || [];
// Count switches
const switchCount = inputConnections.reduce((count, connection) => {
return count + (connection.inputismotor === true ? 1 : 0);
}, 0);
totalSwitchCount += switchCount;
// Count sensors
if (tank.need_sensor?.toLowerCase() === "yes") {
totalSensorCount++;
}
// Determine all_motor_status
const allMotorStatus = inputConnections.some(connection => connection.motor_status === "2");
// Add switch_count and all_motor_status to the response
return {
...tank.toObject(), // Convert Mongoose document to plain object
connections: {
...tank.connections,
switch_count: switchCount,
},
all_motor_status: allMotorStatus, // Add all_motor_status field
};
});
reply.send({
status_code: 200,
data: transformedDocs,
count: transformedDocs.length,
total_switch_count: totalSwitchCount,
total_sensor_count: totalSensorCount,
});
})
.catch((err) => {
console.error(err);
reply.send({ status_code: 500, error: err.message });
});
} catch (err) {
console.error(err);
reply.send({ status_code: 500, error: "Internal Server Error" });
}
};
exports.getTanksensorcount = async (req, reply) => {
try {
const { customerId } = req.params;
// Find all tanks for the given customerId
const tanks = await Tank.find({ customerId });
if (!tanks || tanks.length === 0) {
return reply.send({
message: "No tanks found for the given customerId",
data: [],
});
}
// Process each tank
const tankResults = tanks.map(tank => {
const needSensorCount = {
YES: tank.need_sensor === "YES" ? 1 : 0,
};
const inputConnections = tank.connections.inputConnections || [];
const inputIsMotorCounts = inputConnections.reduce(
(acc, connection) => {
if (connection.inputismotor === true) acc.true += 1;
return acc;
},
{ true: 0 }
);
const totalInputConnections = inputConnections.length;
return {
tankName: tank.tankName,
needSensorCount,
inputIsMotorCounts,
totalInputConnections,
inputConnections,
};
});
reply.send({
customerId,
tanks: tankResults,
});
} catch (error) {
reply.status(500).send({ error: "An error occurred while fetching the data." });
}
},
exports.getTanksofParticularInstaller = async (req, reply) => {
try {
await Tank.find({InstallerId: req.query.InstallerId})
.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.getTanklevels = async (req, reply) => {
// try {
// const customerId = req.params.customerId;
// const tankName = req.query.tankName;
// setInterval(async function () {
// const randomNumber = Math.floor(Math.random() * (5500 - 1000) + 1000);
// console.log(randomNumber)
// console.log( await Tank.findOneAndUpdate({ customerId: customerId, tankName: tankName }, { $set: { waterlevel: randomNumber } }));
// }, 2000);
// return { message: 'Water level will be updated every 2 seconds' };
//}
// catch (err) {
// throw boom.boomify(err);
// }
//};
// const boom = require("@hapi/boom"); // Assuming you are using boom for error handling
exports.getTankmotordata = async (req, reply) => {
try {
const { startDate, stopDate,pumps,users } = req.body;
const { customerId } = req.params;
// 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 input dates to ISO 8601 format for Date comparison
const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").endOf('day').toDate();
// Convert input dates to string format for string-based comparison
// Fetch the username based on customerId
const user = await User.findOne({ customerId }).select("username");
if (user) {
const userName = user.username || "N/A";
let query = { customerId };
if (pumps !== "All") {
query.motor_id = pumps;
}
if (users !== "All") {
query.started_by = users;
}
// Fetch motor data with applied filters
const motordatas = await MotorData.find(query);
const filtereddatas = motordatas.filter((record) => {
const recordTime = moment(record.startTime, "DD-MMM-YYYY - HH:mm").toDate();
return recordTime >= start && recordTime <= end;
});
reply.send({
status_code: 200,
data: filtereddatas,
count: filtereddatas.length,
customerName: userName,
});
} else {
reply.send({ status_code: 404, message: "User not found" });
}
} catch (err) {
console.error("Error in getTankmotordata:", err);
throw boom.boomify(err);
}
};
exports.updateTanklevels = async (req, reply) => {
try {
const customerId = req.params.customerId;
const tanks = await Tank.find({ customerId,tankLocation:"overhead" });
const intervals = {};
for (const tank of tanks) {
const tankId = tank._id;
const tank_name = tank.tankName
let capacity = parseInt(tank.capacity.replace(/,/g, ''), 10);
//let waterLevel = parseInt(tank.waterlevel.replace(/,/g, ''), 10);
const intervalId = setInterval(async function () {
const tank_data = await Tank.findOne({ _id:tankId });
const motorStatus = tank_data.motor_status
let waterLevel = parseInt(tank_data.waterlevel.replace(/,/g, ''), 10);
const newWaterLevel = Math.floor(waterLevel - 150);
console.log("motorstatus:"+motorStatus)
if (newWaterLevel <= 0 ) {
clearInterval(intervals[tankId]);
console.log(`Stopped updating tank with ID ${tankId}`);
return;
}
else{
const result = await Tank.findOneAndUpdate(
{ _id: tankId },
{ $set: { waterlevel: newWaterLevel } }
);
console.log(tank_name+"="+newWaterLevel)
}
// console.log(result);
// waterLevel = newWaterLevel;
}, 5000);
intervals[tankId] = intervalId;
}
return { message: 'Water level updates started' };
} catch (err) {
throw boom.boomify(err);
}
};
exports.getTanklevels = async (req, reply) => {
try {
const customerId = req.params.customerId;
let sumSumpDrinkingWater = 0;
let totalavailableDrinkingwater = 0;
let totalDrinkingcapacity = 0;
let totalavailableBorewater = 0;
let totalBorewatercapacity = 0;
let sumOverheadDrinkingWater = 0;
let sumSumpBoreWater = 0;
let sumOverheadBoreWater = 0;
let sumSumpDrinkingWaterCapacity = 0;
let sumOverheadDrinkingWaterCapacity = 0;
let sumSumpBoreWaterCapacity = 0;
let sumOverheadBoreWaterCapacity = 0;
// Fetch only active tanks
const updated_data = await Tank.find({ customerId: customerId, status: "active" });
console.log("Active Tanks Data:", updated_data);
updated_data.forEach((tank) => {
const waterlevel = parseInt(tank.waterlevel ? tank.waterlevel.replace(/,/g, '') : '0', 10);
const capacity = parseInt(tank.capacity ? tank.capacity.replace(/,/g, '') : '0', 10);
const waterlevelPercentage = ((waterlevel / capacity) * 100).toFixed(2);
tank.waterlevelPercentage = waterlevelPercentage; // Add water level percentage to each tank object
console.log(`Processing tank: ${tank.tankName}`);
let totalInputPercentage = 0;
let inputCount = 0;
let totalOutputPercentage = 0;
let outputCount = 0;
// Process input connections
if (tank.connections.inputConnections) {
tank.connections.inputConnections.forEach(inputConnection => {
if (inputConnection.status === "active") { // Process only active connections
const inputWaterLevel = inputConnection.water_level ? parseInt(inputConnection.water_level.replace(/,/g, ''), 10) : 0;
const inputCapacity = inputConnection.capacity ? parseInt(inputConnection.capacity.replace(/,/g, ''), 10) : 0;
if (inputCapacity > 0) {
inputConnection.waterlevelPercentage = ((inputWaterLevel / inputCapacity) * 100).toFixed(2);
totalInputPercentage += parseFloat(inputConnection.waterlevelPercentage);
inputCount++;
} else {
inputConnection.waterlevelPercentage = null;
}
}
});
tank.connections.inputWaterlevelPercentage = inputCount > 0 ? (totalInputPercentage / inputCount).toFixed(2) : null;
}
// Process output connections
if (tank.connections.outputConnections) {
tank.connections.outputConnections.forEach(outputConnection => {
if (outputConnection.status === "active") { // Process only active connections
const outputWaterLevel = outputConnection.water_level ? parseInt(outputConnection.water_level.replace(/,/g, ''), 10) : 0;
const outputCapacity = outputConnection.capacity ? parseInt(outputConnection.capacity.replace(/,/g, ''), 10) : 0;
if (outputCapacity > 0) {
outputConnection.waterlevelPercentage = ((outputWaterLevel / outputCapacity) * 100).toFixed(2);
totalOutputPercentage += parseFloat(outputConnection.waterlevelPercentage);
outputCount++;
} else {
outputConnection.waterlevelPercentage = null;
}
}
});
tank.connections.outputWaterlevelPercentage = outputCount > 0 ? (totalOutputPercentage / outputCount).toFixed(2) : null;
}
// Summing up the total water levels and capacities for active tanks only
if (tank.tankLocation === 'sump' && tank.typeOfWater === 'drinking') {
sumSumpDrinkingWater += waterlevel;
sumSumpDrinkingWaterCapacity += capacity;
} else if (tank.tankLocation === 'overhead' && tank.typeOfWater === 'drinking') {
sumOverheadDrinkingWater += waterlevel;
sumOverheadDrinkingWaterCapacity += capacity;
} else if (tank.tankLocation === 'sump' && tank.typeOfWater === 'bore') {
sumSumpBoreWater += waterlevel;
sumSumpBoreWaterCapacity += capacity;
} else if (tank.tankLocation === 'overhead' && tank.typeOfWater === 'bore') {
sumOverheadBoreWater += waterlevel;
sumOverheadBoreWaterCapacity += capacity;
}
else if ( tank.typeOfWater === 'drinking') {
totalavailableDrinkingwater += waterlevel;
totalDrinkingcapacity += capacity;
}
else if ( tank.typeOfWater === 'bore') {
totalavailableBorewater += waterlevel;
totalBorewatercapacity += capacity;
}
});
const user = await User.findOne({ customerId: customerId });
const buildingName = user ? user.buildingName : null;
const address1 = user ? user.profile.address1 : null;
const responseData = {
status_code: 200,
data: updated_data,
totalDrinkingWaterInSump: sumSumpDrinkingWater,
totalDrinkingWaterInOverhead: sumOverheadDrinkingWater,
totalBoreWaterInSump: sumSumpBoreWater,
totalBoreWaterInOverhead: sumOverheadBoreWater,
totalDrinkingWaterInSumpCapacity: sumSumpDrinkingWaterCapacity,
totalDrinkingWaterInOverheadCapacity: sumOverheadDrinkingWaterCapacity,
totalBoreWaterInSumpCapacity: sumSumpBoreWaterCapacity,
totalBoreWaterInOverheadCapacity: sumOverheadBoreWaterCapacity,
buildingName: buildingName,
address1: address1,
};
if (!reply.sent) {
reply.send(responseData);
}
} catch (err) {
if (!reply.sent) {
reply.code(500).send({ error: 'Internal Server Error' });
}
throw boom.boomify(err);
}
};
const intervals = {};
let sump_water_levels=[];
let supplier_tanks = [];
// exports.motorAction = async (req, reply) => {
// try {
// 7
// const customerId = req.params.customerId;
// const action = req.body.action
// const receiver_tank = req.body.to
// const receiver_tank_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:(req.body.to_type).toLowerCase()});
// const receiver_capacity = parseInt((receiver_tank_info.capacity).replace(/,/g, ''), 10)
// const desired_water_percentage = parseInt((req.body.percentage).replace(/,/g, ''), 10)
// const supplier_tank = req.body.from
// const supplier_tank_type = (req.body.from_type).toLowerCase()
// const receiver_type = (req.body.to_type).toLowerCase()
// // console.log(supplier_tank)
// // const suplr_tank_info1 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// const interval_variable = supplier_tank+receiver_tank
// let currentTank = supplier_tanks.find(tank => tank.supplier_tank === supplier_tank);
// let currentSump = sump_water_levels.find(tank => tank.supplier_tank === supplier_tank);
// if(action === "start"){
// if (!currentTank) {
// currentTank = {
// supplier_tank: supplier_tank,
// start_time: new Date().toLocaleString('en-US', { timeZone: 'Asia/Kolkata' })
// };
// supplier_tanks.push(currentTank);
// }
// // start_time = new Date().toLocaleString('en-US', {timeZone: 'Asia/Kolkata'})
// console.log(supplier_tanks)
// // const stop_at = req.body.stop_at
// if(supplier_tank_type==="sump" && receiver_type === "overhead"){
// await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: "1" } });
// const supplier_tank_info1 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// //console.log(supplier_tank_info1)
// //const initial_update = parseInt(supplier_tank_info1.waterlevel.replace(/,/g, ''), 10)-200;
// // await Tank.findOneAndUpdate({customerId, tankName: supplier_tank,tankLocation:supplier_tank_type}, { $set: { waterlevel: initial_update } });
// const supplier_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// const sump_water_level= parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
// const receiver_tank_info2 = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:(req.body.to_type).toLowerCase()});
// const water_added_from_midnight = parseInt((receiver_tank_info2.total_water_added_from_midnight).replace(/,/g, ''), 10)
// if (!currentSump) {
// currentSump = {
// supplier_tank: supplier_tank,
// supplier_initial_waterlevel:sump_water_level,
// receiver_tank_total_water_added_from_midnight:water_added_from_midnight
// };
// sump_water_levels.push(currentSump);
// }
// console.log(sump_water_levels)
// const overheadTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = overheadTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "1";
// await overheadTank.save();
// }
// // await changingfrom_tankwaterlevel(customerId,initial_update,supplier_tank_info);
// // let supplier_waterlevel = parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
// // console.log(supplier_waterlevel)
// // let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
// intervals[interval_variable] = setInterval(async function () {
// // Calculate new water levels
// const supplier_tank_info2 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
// let receiver_waterlevel = parseInt(rcvr_info.waterlevel.replace(/,/g, ''), 10)
// let supplier_waterlevel = parseInt(supplier_tank_info2.waterlevel.replace(/,/g, ''), 10)
// const newWaterLevel = receiver_waterlevel + 250//Math.floor(supplier_waterlevel * 0.1);
// const newSupplierWaterLevel = supplier_waterlevel-250//Math.floor(supplier_waterlevel * 0.1);
// const supplier_capacity = parseInt(supplier_tank_info.capacity.replace(/,/g, ''), 10)
// console.log((newSupplierWaterLevel/supplier_capacity)*100)
// // Check if updating should stop
// if ((newSupplierWaterLevel/supplier_capacity)*100 <= 5 || (newWaterLevel/receiver_capacity)*100 >= 95 || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === "0") {
// console.log((newSupplierWaterLevel/supplier_capacity)*100,(newWaterLevel/receiver_capacity)*100,(newWaterLevel/receiver_capacity)*100,)
// clearInterval(intervals[interval_variable]); // Clear the interval for this tank
// delete intervals[interval_variable];
// const overheadTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = overheadTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "0";
// await overheadTank.save();
// }
// // Find the tank based on customerId, tankName, and tankLocation
// const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// // Check if all objects in inputConnections have motor_status === "0"
// const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");
// if (allMotorStatusZero) {
// // Update the motor_status field to "0" for the tank
// await Tank.findOneAndUpdate(
// { customerId, tankName: receiver_tank, tankLocation: receiver_type },
// { $set: { motor_status: "0" } }
// );
// }
// console.log("end for"+receiver_tank);
// } else {
// // Update water levels in database
// //supplier_waterlevel = newSupplierWaterLevel;
// // receiver_waterlevel = newWaterLevel;
// console.log((newSupplierWaterLevel/supplier_capacity)*100)
// // console.log((newWaterLevel/receiver_capacity)*100)
// console.log(newWaterLevel+""+receiver_type)
// console.log(newSupplierWaterLevel+""+supplier_tank)
// await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { waterlevel: newWaterLevel } })
// await Tank.findOneAndUpdate({customerId, tankName: supplier_tank,tankLocation:supplier_tank_type}, { $set: { waterlevel: newSupplierWaterLevel } })
// //if (supplier_tank_info2.motor_status==="0"){
// // await Tank.findOneAndUpdate({customerId, tankName: supplier_tank,tankLocation:supplier_tank_type}, { $set: { waterlevel: supplier_waterlevel } })
// // }
// }
// }, 2000);
// }
// // if(supplier_tank_type==="sump" && receiver_type === "sump"){
// // await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: 1 } });
// // // console.log(rcvr_info.motor_status)
// // // const supplier_tank_info1 = await Tank.findOne({ customerId ,tankName:supplier_tank});
// // // initial_update = parseInt(supplier_tank_info1.capacity.replace(/,/g, ''), 10)/2;
// // // await Tank.findOneAndUpdate({customerId, tankName: supplier_tank}, { $set: { waterlevel: initial_update } });
// // const supplier_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// // let supplier_waterlevel = parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
// // let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
// // intervals[interval_variable] = setInterval(async function () {
// // const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
// // const supplier_capacity = parseInt(supplier_tank_info.capacity.replace(/,/g, ''), 10)
// // // Calculate new water levels
// // const newWaterLevel = receiver_waterlevel + 200//Math.floor(supplier_waterlevel * 0.1);
// // const newSupplierWaterLevel = Math.min(supplier_capacity, supplier_waterlevel - 200);// Math.floor(supplier_waterlevel * 0.15));
// // // console.log(newWaterLevel)
// // // console.log(newSupplierWaterLevel)
// // // console.log(rcvr_info.motor_status)
// // // console.log(rcvr_info.tankName)
// // // Check if updating should stop
// // if ( (newWaterLevel/receiver_capacity)*100 >= 95 || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === 0 || (newSupplierWaterLevel/supplier_capacity)*100 <= 5) {
// // clearInterval(interval_variable)
// // delete intervals[interval_variable];
// // await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: 0 } });
// // console.log("end");
// // } else {
// // // Update water levels in database
// // supplier_waterlevel = newSupplierWaterLevel;
// // receiver_waterlevel = newWaterLevel;
// // console.log(supplier_waterlevel,"0")
// // console.log(receiver_waterlevel,"1")
// // // console.log((newSupplierWaterLevel/supplier_capacity)*100)
// // // console.log((newWaterLevel/receiver_capacity)*100)
// // await Promise.all([
// // Tank.findOneAndUpdate({customerId, tankName: receiver_tank}, { $set: { waterlevel: newWaterLevel } }),
// // Tank.findOneAndUpdate({customerId, tankName: supplier_tank}, { $set: { waterlevel: newSupplierWaterLevel } })
// // ]);
// // }
// // }, 2000);
// // }
// if(supplier_tank_type==="sump" && receiver_type === "sump"){
// const receiver_capacity = parseInt(receiver_tank_info.capacity.replace(/,/g, ''), 10)
// const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "1";
// await sumpTank.save();
// }
// // console.log(receiver_capacity,"0",receiver_tank_info.tankName)
// await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: "1" } });
// const supplier_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// // let supplier_waterlevel = parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
// // let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
// // console.log(receiver_waterlevel,"1")
// intervals[interval_variable] = setInterval(async function () {
// // Calculate new water levels
// const splr_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
// const supplier_capacity = parseInt(supplier_tank_info.capacity.replace(/,/g, ''), 10)
// let supplier_waterlevel = parseInt(splr_tank_info.waterlevel.replace(/,/g, ''), 10)
// let receiver_waterlevel = parseInt(rcvr_info.waterlevel.replace(/,/g, ''), 10)
// // Calculate new water levels
// const newWaterLevel = receiver_waterlevel + 250//Math.floor(supplier_waterlevel * 0.1);
// const newSupplierWaterLevel = Math.min(supplier_capacity, supplier_waterlevel - 250);// Math.floor(supplier_waterlevel * 0.15));
// // Check if updating should stop
// if ((newWaterLevel/receiver_capacity)*100 >= 97 || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === "0" || (newSupplierWaterLevel/supplier_capacity)*100 <= 5 ) {
// clearInterval(intervals[interval_variable]); // Clear the interval for this tank
// delete intervals[interval_variable];
// const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "0";
// await sumpTank.save();
// }
// }
// const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// // Check if all objects in inputConnections have motor_status === "0"
// const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");
// if (allMotorStatusZero) {
// // Update the motor_status field to "0" for the tank
// await Tank.findOneAndUpdate(
// { customerId, tankName: receiver_tank, tankLocation: receiver_type },
// { $set: { motor_status: "0" } }
// );
// console.log("end for" + receiver_tank);
// } else {
// // Update water levels in database
// // supplier_waterlevel = newSupplierWaterLevel;
// // receiver_waterlevel = newWaterLevel;
// console.log(supplier_waterlevel,"0")
// console.log(receiver_waterlevel,"1")
// // console.log((newSupplierWaterLevel/supplier_capacity)*100)
// // console.log((newWaterLevel/receiver_capacity)*100)
// await Promise.all([
// Tank.findOneAndUpdate({customerId, tankName: receiver_tank}, { $set: { waterlevel: newWaterLevel } }),
// Tank.findOneAndUpdate({customerId, tankName: supplier_tank}, { $set: { waterlevel: newSupplierWaterLevel } })
// ]);
// }
// }, 2000);
// }
// if(supplier_tank_type==="bore" && receiver_type === "sump"){
// const receiver_capacity = parseInt(receiver_tank_info.capacity.replace(/,/g, ''), 10)
// // console.log(receiver_capacity,"0",receiver_tank_info.tankName)
// await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: "1" } });
// const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "1";
// await sumpTank.save();
// }
// // let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
// // console.log(receiver_waterlevel,"1")
// intervals[interval_variable] = setInterval(async function () {
// // Calculate new water levels
// const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
// //console.log(rcvr_info)
// let receiver_waterlevel = parseInt(rcvr_info.waterlevel.replace(/,/g, ''), 10)
// //console.log(rcvr_info.motor_status)
// const newWaterLevel = receiver_waterlevel+250;
// //console.log(newWaterLevel,"2",receiver_tank_info.tankName)
// // Check if updating should stop
// if ((newWaterLevel/receiver_capacity)*100 >= 97 || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === "0" ) {
// clearInterval(intervals[interval_variable]); // Clear the interval for this tank
// delete intervals[interval_variable];
// const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "0";
// await sumpTank.save();
// }
// const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// // Check if all objects in inputConnections have motor_status === "0"
// const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");
// if (allMotorStatusZero) {
// // Update the motor_status field to "0" for the tank
// await Tank.findOneAndUpdate(
// { customerId, tankName: receiver_tank, tankLocation: receiver_type },
// { $set: { motor_status: "0" } }
// );
// }
// console.log("end for" + receiver_tank);
// } else {
// // Update water levels in database
// // receiver_waterlevel = newWaterLevel;
// //console.log((newWaterLevel/receiver_capacity)*100,"4",receiver_tank_info.tankName)
// await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { waterlevel: newWaterLevel } })
// console.log(receiver_tank+"="+newWaterLevel+"="+"bore to sump")
// }
// }, 2000);
// }
// // console.log(customerId,req.body.from,req.body.from_type,receiver_tank,req.body.to_type,)
// }
// else if (action === "stop") {
// //stop_time = new Date().toLocaleString('en-US', {timeZone: 'Asia/Kolkata'})
// clearInterval(intervals[interval_variable]); // Clear the interval for this tank
// delete intervals[interval_variable];
// const stopTime = new Date().toLocaleString('en-US', { timeZone: 'Asia/Kolkata' });
// // console.log(currentTank.start_time)
// const startTime = currentTank.start_time;
// // const duration = calculateDuration(startTime, stopTime);
// // Store the duration or perform any required operations
// supplier_tanks = supplier_tanks.filter(tank => tank.supplier_tank !== supplier_tank);
// // console.log(supplier_tanks)
// // storing data of how amny water supplied from sump to overhead to calculate the consumption
// const suplr_tank_info2 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
// let water_added_from_midnight1=0
// if (supplier_tank_type === "sump") {
// // const rcvr_info2 = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
// console.log(currentSump.receiver_tank_total_water_added_from_midnight,"5")
// water_added_from_midnight1=currentSump.receiver_tank_total_water_added_from_midnight
// console.log(water_added_from_midnight1)
// }
// const sump_water_level1 =currentSump.supplier_initial_waterlevel
// console.log(sump_water_level1,"1")
// // console.log(water_added_from_midnight)
// const sump_final_water_level= parseInt(suplr_tank_info2.waterlevel.replace(/,/g, ''), 10)
// console.log(sump_final_water_level,"2")
// sump_water_levels = sump_water_levels.filter(tank => tank.supplier_tank !== supplier_tank);
// const quantity_delivered = Math.abs(sump_water_level1 - sump_final_water_level);
// if (supplier_tank_type === "sump") {
// final_added_water=water_added_from_midnight1+quantity_delivered
// await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { total_water_added_from_midnight: final_added_water } })
// }
// const overheadTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// const connection = overheadTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
// if (connection) {
// connection.motor_status = "0";
// await overheadTank.save();
// }
// const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
// // Check if all objects in inputConnections have motor_status === "0"
// const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");
// if (allMotorStatusZero) {
// console.log(allMotorStatusZero)
// // Update the motor_status field to "0" for the tank
// await Tank.findOneAndUpdate(
// { customerId, tankName: receiver_tank, tankLocation: receiver_type },
// { $set: { motor_status: "0" } }
// );
// }
// //saving the motor run time and data
// motorData = {
// customerId:customerId,
// supplierTank : supplier_tank,
// supplier_type: supplier_tank_type,
// receiverTank: receiver_tank,
// receiver_type: receiver_type,
// startTime: startTime,
// stopTime: stopTime,
// quantity_delivered:quantity_delivered
// };
// var motorData = new MotorData(motorData);
// checkFormEncoding = isUserFormUrlEncoded(req);
// if (checkFormEncoding.isUserFormUrlEncoded) {
// usertobeInserted = checkFormEncoding.motorData;
// console.log("thsi true url string");
// motorData.customerId = customerId;
// motorData.supplierTank = supplierTank;
// motorData.receiverTank = receiver_tank;
// motorData.supplier_type = supplier_type;
// motorData.receiver_type = receiver_type;
// motorData.startTime = startTime;
// motorData.stopTime = stopTime;
// motorData.quantity_delivered = quantity_delivered;
// }
// const motor_data = await motorData.save();
// console.log(motor_data)
// // reply.send({ status_code: 200, data: motor_data });
// // reply.send({ status_code: 200, "start time": start_time, data: motor_data});
// // console.log(start_time)
// // return motor_data
// // console.log(stop_time)
// // clearInterval(intervalId);
// // await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:(req.body.to_type).toLowerCase()}, { $set: { motor_status: "0" } });
// reply.send({ status_code: 200, "stop time": stopTime,data: motor_data});
// } else {
// throw new Error("Invalid action");
// }
// return { message: 'Water level updates started' };
// } catch (err) {
// throw new Error(`Failed to start/stop water level updates: ${err.message}`);
// };
// };
// exports.consumption = async (request, reply) => {
// try {
// const customerId = req.params.customerId;
// const tanks = await Tank.find({ customerId,tankLocation:"overhead"});
// const tankData = [];
// for (const tank of tanks) {
// const tankId = tank._id;
// const waterlevel_at_midnight = parseInt(tank.waterlevel_at_midnight.replace(/,/g, ''), 10);
// const total_water_added_from_midnight = parseInt(tank.total_water_added_from_midnight.replace(/,/g, ''), 10);
// const waterlevel = parseInt(tank.waterlevel.replace(/,/g, ''), 10);
// const tankname = tank.tankName
// const consumption = (waterlevel_at_midnight+total_water_added_from_midnight)-waterlevel
// tankData.push({ tankname, waterLevel: consumption });
// // console.log(newWaterLevel);
// }
// reply.send({ status_code: 200, tankData });
// return { message: 'Water level updates started' };
// } catch (err) {
// throw boom.boomify(err);
// }
exports.consumption = async (request, reply) => {
try {
const { customerId } = request.params;
const { startDate, stopDate, block } = request.body;
let typeofwater = request.body.typeofwater.toLowerCase();
// Convert typeofwater to lowercase
typeofwater = typeofwater.toLowerCase();
const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();
// Construct the query object
const tankQuery = { customerId, tankLocation: "overhead" };
if (block !== "All") tankQuery.blockName = block;
// Add typeofwater filter
if (typeofwater === "bore") {
tankQuery.typeOfWater = { $in: ["bore", "Bore Water"] };
} else if (typeofwater === "drinking") {
tankQuery.typeOfWater = { $in: ["drinking", "Drinking Water"] };
}
const tanks = await Tank.find(tankQuery);
const tankData = [];
const tankconsumptionData = [];
let totalConsumptionForSelectedBlockAndTypeOfWater = 0;
let totalBoreConsumptionForSelectedBlockAndTypeOfWater = 0;
let totalBoreCapacityForSelectedBlockAndTypeOfWater = 0;
let totalDrinkingConsumptionForSelectedBlockAndTypeOfWater = 0;
let totalDrinkingCapacityForSelectedBlockAndTypeOfWater = 0;
for (const tank of tanks) {
const waterlevel_at_midnight = parseInt(tank.waterlevel_at_midnight.replace(/,/g, ''), 10);
const total_water_added_from_midnight = parseInt(tank.total_water_added_from_midnight.replace(/,/g, ''), 10);
const waterlevel = parseInt(tank.waterlevel.replace(/,/g, ''), 10);
const tankname = tank.tankName;
const capacity = parseInt(tank.capacity.replace(/,/g, ''), 10);
const tankConsumptions = await TankConsumptionOriginalSchema.find({
customerId,
tankName: tank.tankName,
tankLocation: tank.tankLocation,
...(block !== "All" && { block: tank.blockName }),
...(typeofwater === "bore" && { typeofwater: { $in: ["bore", "Bore Water"] } }),
...(typeofwater === "drinking" && { typeofwater: { $in: ["drinking", "Drinking Water"] } }),
});
let filteredConsumptions;
if (start.getTime() === end.getTime()) {
// If start and end are the same, filter for exact match
filteredConsumptions = tankConsumptions.filter((record) => {
return moment(record.time, "DD-MMM-YYYY - HH:mm").toDate().getTime() === start.getTime();
});
} else {
// Normal range filter
filteredConsumptions = tankConsumptions.filter((record) => {
const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").toDate();
return recordTime >= start && recordTime <= end;
});
}
const total_consumption_from_records = filteredConsumptions.reduce((acc, record) => {
return acc + parseInt(record.consumption, 10);
}, 0);
let consumption;
// const isSameTime = start.getTime() === end.getTime();
// const isEndToday = moment(end).isSame(moment(), 'day');
// if (isSameTime || !isEndToday) {
// // If single timestamp OR end is not today, only use records
// consumption = total_consumption_from_records;
// } else {
// // If end is today, add real-time values
// consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel + total_consumption_from_records;
// }
const isSameTime = start.getTime() === end.getTime();
const isEndToday = moment(end).isSame(moment(), 'day');
if (isSameTime && isEndToday) {
// Start and End are same AND it's today => only realtime tank calc
consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel;
} else if (isSameTime && !isEndToday) {
// Same time and NOT today => only record data
consumption = total_consumption_from_records;
} else if (!isSameTime && isEndToday) {
// Range query ending today => combine record + realtime
consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel + total_consumption_from_records;
} else {
// Range query not ending today => only record data
consumption = total_consumption_from_records;
}
// const isSameTime = start.getTime() === end.getTime();
// const isToday = moment(start).isSame(moment(), 'day');
// if (isSameTime && !isToday) {
// // Same date & time and NOT today => use only records
// consumption = total_consumption_from_records;
// } else {
// // Normal case => use full calculation
// consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel + total_consumption_from_records;
// }
// Add to the total consumption and capacities based on water type
if (tank.typeOfWater === "bore" || tank.typeOfWater === "Bore Water") {
totalBoreConsumptionForSelectedBlockAndTypeOfWater += consumption;
totalConsumptionForSelectedBlockAndTypeOfWater += consumption
totalBoreCapacityForSelectedBlockAndTypeOfWater += capacity;
} else if (tank.typeOfWater === "drinking" || tank.typeOfWater === "Drinking Water") {
totalDrinkingConsumptionForSelectedBlockAndTypeOfWater += consumption;
totalConsumptionForSelectedBlockAndTypeOfWater += consumption
totalDrinkingCapacityForSelectedBlockAndTypeOfWater += capacity;
}
tankData.push({
tankname,
totalConsumption: consumption,
block: tank.blockName,
TypeofWater: tank.typeOfWater,
location: tank.tankLocation,
capacity: tank.capacity,
waterlevel: tank.waterlevel,
});
tankconsumptionData.push({
tankname,
consumptionRecordsdatewise: filteredConsumptions,
});
}
// Calculate total consumption percentages
const boreConsumptionPercentage = totalBoreCapacityForSelectedBlockAndTypeOfWater
? ((totalBoreConsumptionForSelectedBlockAndTypeOfWater / totalBoreCapacityForSelectedBlockAndTypeOfWater) * 100).toFixed(2)
: 0;
const drinkingConsumptionPercentage = totalDrinkingCapacityForSelectedBlockAndTypeOfWater
? ((totalDrinkingConsumptionForSelectedBlockAndTypeOfWater / totalDrinkingCapacityForSelectedBlockAndTypeOfWater) * 100).toFixed(2)
: 0;
const totalConsumptionPercentage =
typeofwater === "bore"
? boreConsumptionPercentage
: typeofwater === "drinking"
? drinkingConsumptionPercentage
: ((totalBoreConsumptionForSelectedBlockAndTypeOfWater + totalDrinkingConsumptionForSelectedBlockAndTypeOfWater) /
(totalBoreCapacityForSelectedBlockAndTypeOfWater + totalDrinkingCapacityForSelectedBlockAndTypeOfWater) *
100
).toFixed(2);
// Include the total consumption in the response
// Construct the response
const response = {
status_code: 200,
tankData,
consumptiorecordsdatewise: tankconsumptionData,
totalConsumptionPercentage,
totalConsumptionPercentageForBore: typeofwater !== "drinking" ? boreConsumptionPercentage : 0,
totalConsumptionPercentageForDrinking: typeofwater !== "bore" ? drinkingConsumptionPercentage : 0,
totalConsumptionForBore: typeofwater !== "drinking" ? totalBoreConsumptionForSelectedBlockAndTypeOfWater : 0,
totalConsumptionForDrinking: typeofwater !== "bore" ? totalDrinkingConsumptionForSelectedBlockAndTypeOfWater : 0,
[`total consumption of all and selected block`]: totalConsumptionForSelectedBlockAndTypeOfWater
};
// Send the response
reply.send(response);
} catch (err) {
throw boom.boomify(err);
}
};
exports.consumptiondatewiseofalltanks = async (request, reply) => {
try {
const { customerId } = request.params;
const { startDate, stopDate, block } = request.body;
let { typeofwater } = request.body;
typeofwater = typeofwater.toLowerCase();
const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();
const tankQuery = { customerId, tankLocation: "overhead" };
if (block !== "All") {
tankQuery.blockName = block;
}
if (typeofwater !== "all") {
tankQuery.typeOfWater = typeofwater;
}
const tanks = await Tank.find(tankQuery);
const tankconsumptionData = {};
let totalConsumptionForSelectedBlockAndTypeOfWater = 0;
let totalAvailableCapacity = 0;
let totalConsumed = 0;
for (const tank of tanks) {
const tankname = tank.tankName;
const tankConsumptions = await TankConsumptionOriginalSchema.find({
customerId,
tankName: tankname,
tankLocation: tank.tankLocation,
...(block !== "All" && { block: tank.blockName }),
...(typeofwater !== "all" && { typeofwater: tank.typeOfWater })
});
let filteredConsumptions;
if (start.getTime() === end.getTime()) {
// If start and end are the same, filter for exact match
filteredConsumptions = tankConsumptions.filter((record) => {
return moment(record.time, "DD-MMM-YYYY - HH:mm").toDate().getTime() === start.getTime();
});
} else {
// Normal range filter
filteredConsumptions = tankConsumptions.filter((record) => {
const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").toDate();
return recordTime >= start && recordTime <= end;
});
}
// filteredConsumptions.forEach(record => {
// totalConsumed += parseInt(record.consumption, 10);
// totalAvailableCapacity += parseInt(record.capacity, 10);
// });
for (const record of filteredConsumptions) {
const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").format("DD-MMM-YYYY - HH:mm");
const tank_info = await Tank.findOne({
customerId:record.customerId,
tankName: record.tankName,
tankLocation: record.tankLocation,
});
totalConsumptionForSelectedBlockAndTypeOfWater+=parseInt(record.consumption, 10);
totalConsumed += parseInt(record.consumption, 10);
;
// console.log( parseInt(tank_info.capacity.replace(/,/g, ''), 10))
totalAvailableCapacity += parseInt(tank_info.capacity.replace(/,/g, ''), 10)
if (!tankconsumptionData[recordTime]) {
tankconsumptionData[recordTime] = {
date: recordTime,
consumptionRecordsdatewise: [],
count: 0
};
}
const recordExists = tankconsumptionData[recordTime].consumptionRecordsdatewise.some(r => r.tankName === record.tankName);
if (!recordExists) {
tankconsumptionData[recordTime].consumptionRecordsdatewise.push({
tankName: record.tankName,
consumption: record.consumption,
available_capacity: record.available_capacity,
time: record.time
});
tankconsumptionData[recordTime].count++;
}
}
}
const responseData = Object.values(tankconsumptionData);
const totalConsumptionPercentage = totalAvailableCapacity > 0 ? ((totalConsumed / totalAvailableCapacity) * 100).toFixed(2) : "0";
console.log(totalConsumed,"totalConsumed",totalAvailableCapacity,"totalAvailableCapacity",totalConsumptionForSelectedBlockAndTypeOfWater,"totalConsumptionForSelectedBlockAndTypeOfWater")
const response = {
status_code: 200,
consumptiorecordsdatewise: responseData,
[`total consumption of ${typeofwater} and selected block`]: totalConsumptionForSelectedBlockAndTypeOfWater,
totalConsumptionPercentage: `${totalConsumptionPercentage}%`
};
reply.send(response);
} catch (err) {
throw boom.boomify(err);
}
};
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
//const moment = require('moment'); // Import moment.js for date/time operations
const formatDate = (date) => {
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const day = String(date.getDate()).padStart(2, '0');
const month = months[date.getMonth()];
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${day}-${month}-${year} - ${hours}:${minutes}`;
};
const admin = require('firebase-admin');
// Initialize Firebase Admin SDK (make sure this is done once in your app)
// const serviceAccount = require('../waternotifications-ab81a-firebase-adminsdk-ereny-8b0bdac787.json');
const serviceAccount = require('../waternotifications-ab81a-firebase-adminsdk-ereny-8b0bdac787.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
eventEmitter.on(
"motorStart",
async (customerId, fcmTokens, tankName, blockName, startTime, motorOnType, manual_threshold_time, typeOfWater, hw_Id, phoneNumber) => {
try {
console.log("Motor Start Event Triggered for:", customerId);
// Fetch user or staff based on customerId
const user = await User.findOne({ customerId });
if (!user) {
console.log(`No user found for customerId: ${customerId}`);
return;
}
// Identify who started the motor
let startedBy = "Unknown"; // Default value
if (user.phone === phoneNumber) {
startedBy = user.username; // Customer's name
} else {
const staffMember = user.staff.staff.find(staff => staff.phone === phoneNumber);
if (staffMember) {
startedBy = staffMember.name; // Staff's name
}
}
if (startedBy === "Unknown") {
console.log("User not found. Cannot proceed with motorStart event.");
return;
}
const startMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual";
const motorName = `${tankName}-${blockName}-${typeOfWater}`;
const message =
`🚰 Motor Name: ${motorName}\n` +
`🚰 Tank Name: '${tankName}'\n` +
`🏢 Block Name: '${blockName}'\n` +
`👤 Started by: ${startedBy}\n` + // Only name is displayed
`📱 Mode: '${startMethod}'\n` +
`🕒 Pump started at: ${startTime} \n` +
`Will stop after: '${manual_threshold_time}' mins`;
await sendNotification(hw_Id, customerId, fcmTokens, "ARMINTA : MOTOR STARTED", message);
} catch (error) {
console.error("Error in motorStart event:", error);
}
}
);
eventEmitter.on(
"motorStop",
async (
customerId,
fcmTokens,
tankName,
blockName,
stopTime,
motorOnType,
totalWaterPumped,
typeOfWater,
hw_Id,
phoneNumber
) => {
try {
console.log("Motor Stop Event Triggered for:", customerId);
// Fetch user or staff based on customerId
const user = await User.findOne({ customerId });
if (!user) {
console.log(`No user found for customerId: ${customerId}`);
return;
}
// Identify who stopped the motor
let stoppedBy = "Unknown"; // Default value
if (user.phone === phoneNumber) {
stoppedBy = user.username; // Customer's name
} else if (user.staff && user.staff.staff) {
const staffMember = user.staff.staff.find((staff) => staff.phone === phoneNumber);
if (staffMember) {
stoppedBy = staffMember.name; // Staff's name
}
}
if (stoppedBy === "Unknown") {
console.log("User not found. Cannot proceed with motorStop event.");
return;
}
const stopMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual";
const motorName = `${tankName}-${blockName}-${typeOfWater}`;
const message =
`🚰 Motor Name: ${motorName}\n` +
`🛢️ Tank Name: '${tankName}'\n` +
`🏢 Block Name: '${blockName}'\n` +
`👤 Stopped by: ${stoppedBy}\n` + // Only name is displayed
`📱 Mode: '${stopMethod}'\n` +
`🕒 Pump stopped at: ${stopTime}\n` +
`💧 Total water pumped: ${totalWaterPumped} liters\n`;
await sendNotification(hw_Id, customerId, fcmTokens, "ARMINTA : MOTOR STOPPED", message);
} catch (error) {
console.error("Error in motorStop event:", error);
}
}
);
eventEmitter.on(
'motorStartAutomatic',
async (fcmTokens, tankName, blockName, startTime, motorOnType, manual_threshold_time, typeOfWater,threshold) => {
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 === "Automatic" ? "Automatic" : "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` +
`🏢 Block Name: '${blockName}'\n` +
`👤 Started by: '${startMethod}' \n` +
`📱 Mode: "Atomatic System" \n` +
`🕒 Pump started at: ${startTime} \n` +
`Will stop after: '${threshold}' `;
// Send the notification
await sendNotification(fcmTokens, 'Arminta Water Management', message);
} catch (error) {
console.error('Error in motorStart event:', error);
}
}
);
eventEmitter.on('sendHighWaterNotification', async (fcmTokens, tankInfo, startTime, stopTime) => {
const message = `Attention: Water level in '${tankInfo.tankName}' located at '${tankInfo.tankLocation}' is high at ${tankInfo.waterLevel}% (${tankInfo.volumeInLitres} L). Please stop the motor. Motor running from ${startTime} to ${stopTime}.`;
await sendNotification(fcmTokens, 'High Water Level', message, 'Stop Motor');
});
// Event listener for very high water level notification
eventEmitter.on('sendVeryHighWaterNotification', async (fcmTokens, tankInfo, startTime, stopTime) => {
const message = `Attention: Water level in '${tankInfo.tankName}' located at '${tankInfo.tankLocation}' is very high at ${tankInfo.waterLevel}% (${tankInfo.volumeInLitres} L). Please stop the motor. Motor running from ${startTime} to ${stopTime}.`;
await sendNotification(fcmTokens, 'Very High Water Level', message, 'Stop Motor');
});
// Event listener for critically high water level notification
eventEmitter.on('sendCriticalHighWaterNotification', async (fcmTokens, tankInfo, startTime, stopTime) => {
const message = `Attention: Water level in '${tankInfo.tankName}' located at '${tankInfo.tankLocation}' is critically high at ${tankInfo.waterLevel}% (${tankInfo.volumeInLitres} L). Water may overflow. Please stop the motor. Motor running from ${startTime} to ${stopTime}.`;
await sendNotification(fcmTokens, 'Critical High Water Level', message, 'Stop Motor');
});
// Emit high water level event with motorId
// eventEmitter.on('highWaterLevel', async (fcmTokens, timestamp, motorId, waterLevel) => {
// await sendNotification(fcmTokens, 'High Water Level', `Motor ID: ${motorId}, water level reached above 90% at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`);
// });
eventEmitter.on('sendThresholdTimeNotification', async (customerId, fcmTokens, thresholdTime, hw_Id, tankName, blockName) => {
try {
const message =
`🛢️ Tank Name: '${tankName}'\n` +
`🏢 Block Name: '${blockName}'\n` +
`Motor Stopped as it completed ${thresholdTime} minutes.`;
await sendNotification(hw_Id, customerId, fcmTokens, 'Motor Alert', message);
console.log("Threshold time notification sent successfully.");
} catch (error) {
console.error("Error sending threshold time notification:", error);
}
});
// 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 (hw_Id, fcmTokens, waterLevel, blockName, tankName, motorOnType, stopCriteria, typeOfWater, manualThresholdTime) => {
// try {
// const formattedTime = new Date().toLocaleTimeString("en-IN", { timeZone: "Asia/Kolkata" });
// if (motorOnType !== "forced_manual") {
// console.log(`Skipping notification: Motor was started in ${motorOnType} mode.`);
// return;
// }
// const stopConditionMessage = stopCriteria === "manual"
// ? `⚠️ Pump will stop **manually**.`
// : `🚨 Pump will stop when the water level reaches **${manualThresholdTime}%**.`;
// const message = `🚰 **Motor Started** 🚀\n` +
// `🔹 **Motor Name:** ${tankName}-${blockName}-${typeOfWater}\n` +
// `🏢 **Block Name:** ${blockName}\n` +
// `💧 **Water Level:** ${waterLevel}%\n` +
// `📱 **Mode:** Physically Started\n` +
// `🕒 **Pump started at:** ${formattedTime}\n` +
// stopConditionMessage;
// await sendNotification(hw_Id, fcmTokens, "Motor Started 🚀", message);
// console.log(`✅ Motor start notification sent for Motor ID: ${hw_Id}`);
// } catch (error) {
// console.error(`❌ Error in sendMotorStartNotification for Motor ID: ${hw_Id}`, 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 (hw_Id, fcmTokens, waterLevel, blockName, tankName, motorOnType, typeOfWater) => {
// try {
// const formattedTime = new Date().toLocaleTimeString("en-IN", { timeZone: "Asia/Kolkata" });
// const message = `⏹️ **Motor Stopped** 🛑\n` +
// `🔹 **Motor Name:** ${tankName}-${blockName}-${typeOfWater}\n` +
// `🏢 **Block Name:** ${blockName}\n` +
// `💧 **Water Level:** ${waterLevel}%\n` +
// `📱 **Mode:** Forced Manual\n` +
// `🕒 **Pump stopped at:** ${formattedTime}`;
// await sendNotification(hw_Id, fcmTokens, "Motor Stopped 🛑", message);
// console.log(`✅ Motor stop notification sent for Motor ID: ${hw_Id}`);
// } catch (error) {
// console.error(`❌ Error in sendMotorStopNotification for Motor ID: ${hw_Id}`, error);
// }
// }
// );
// 🚀 Motor Start Notification
eventEmitter.on("sendMotorStartNotification", async (hw_Id, customerId, fcmTokens, waterLevel, blockName, tankName, motorOnType, manualThresholdTime) => {
try {
console.log(`✅ Received sendMotorStartNotification event for ${customerId}`);
const formattedTime = new Date().toLocaleTimeString("en-IN", { timeZone: "Asia/Kolkata" });
const normalizedMotorOnType = motorOnType.toLowerCase();
if (normalizedMotorOnType !== "forced_manual") {
console.log(`⚠️ Skipping notification: Motor started in **${motorOnType}** mode.`);
return;
}
if (!Array.isArray(fcmTokens) || fcmTokens.length === 0) {
console.warn(`⚠️ No valid FCM tokens found for Customer ID: ${customerId}`);
return;
}
// const stopConditionMessage = stopCriteria === "level"
// ? `🚨 Pump will stop when the water level reaches **${manualThresholdTime}%**.`
// : `⚠️ Pump will stop **manually**.`;
const message = `🚰 Motor Started 🚀\n` +
`👤 Customer ID: ${customerId}\n` +
`🔹 Motor Name: ${tankName} - ${blockName}\n` +
`💧 Water Level: ${waterLevel}\n` +
`📱 Mode: Manually Started\n` +
`🕒 Pump started at: ${formattedTime}\n`;
await sendNotification(hw_Id, customerId, fcmTokens, "Motor Started 🚀", message);
console.log(`✅ Motor start notification sent for Customer ID: ${customerId}`);
} catch (error) {
console.error(`❌ Error in sendMotorStartNotification for Customer ID: ${customerId}`, error);
}
});
eventEmitter.on("sendMotorStopNotification", async (hw_Id, customerId, fcmTokens, waterLevel, blockName, tankName, motorOnType) => {
try {
console.log(`✅ Received sendMotorStopNotification event for ${customerId}`);
const formattedTime = new Date().toLocaleTimeString("en-IN", { timeZone: "Asia/Kolkata" });
const normalizedMotorOnType = motorOnType.toLowerCase();
if (normalizedMotorOnType !== "forced_manual") {
console.log(`⚠️ Skipping notification: Motor stopped in **${motorOnType}** mode.`);
return;
}
if (!Array.isArray(fcmTokens) || fcmTokens.length === 0) {
console.warn(`⚠️ No valid FCM tokens found for Customer ID: ${customerId}`);
return;
}
const message = `🛑 Motor Stopped ❌\n` +
`👤 Customer ID: ${customerId}\n` +
`🔹 Motor Name: ${tankName} - ${blockName}\n` +
`💧 Water Level: ${waterLevel}\n` +
`📱 Mode: Manually Stopped\n` +
`🕒 Pump stopped at: ${formattedTime}`;
await sendNotification(hw_Id, customerId, fcmTokens, "Motor Stopped ❌", message);
console.log(`✅ Motor stop notification sent for Customer ID: ${customerId}`);
} catch (error) {
console.error(`❌ Error in sendMotorStopNotification for Customer ID: ${customerId}`, error);
}
});
eventEmitter.on('sendLowWaterNotification', async (customerId, fcmTokens, hw_Id, tankName, blockName, lowWaterLevel, currentWaterLevel, currentWaterPercentage) => {
try {
const message =
`⚠️ Warning: Low water level detected!\n` +
`🛢️ Tank Name: '${tankName}'\n` +
`🏢 Block Name: '${blockName}'\n` +
`📉 Low Water Threshold: '${lowWaterLevel} liters'\n` +
`📌 Current Water Level: '${currentWaterLevel} liters'\n` +
`📅 Date & Time: '${new Date().toLocaleString()}'`;
await sendNotification(hw_Id, customerId, fcmTokens, 'Low Water Alert', message);
console.log("✅ Low water notification sent successfully.");
} catch (error) {
console.error("❌ Error sending low water notification:", error);
}
});
eventEmitter.on('sendCriticalLowWaterNotification', async (customerId, fcmTokens, hw_Id, tankName, blockName, criticalLowWaterLevel, currentWaterLevel, currentWaterPercentage) => {
try {
const message =
`🚨 Critical Alert: Water level is **critically low!**\n` +
`🛢️ Tank Name: '${tankName}'\n` +
`🏢 Block Name: '${blockName}'\n` +
`🔴 Critical Low Threshold: '${criticalLowWaterLevel} liters'\n` +
`📌 Current Water Level: '${currentWaterLevel} liters'\n` +
`📅 Date & Time: '${new Date().toLocaleString()}'`;
await sendNotification(hw_Id, customerId, fcmTokens, 'Critical Water Alert', message);
console.log("✅ Critical low water notification sent successfully.");
} catch (error) {
console.error("❌ Error sending critical low water notification:", error);
}
});
// 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 {
// await sendNotification(fcmTokens, "Motor Started", message);
// console.log("Manual method time notification sent successfully.");
// } catch (error) {
// console.error("Error sending thresmanual method time notification:", error);
// }
// });
// eventEmitter.on('sendMotorStopNotification', async (fcmTokens, message) => {
// try {
// await sendNotification(fcmTokens, "Motor Stopped", message);
// console.log("Manual method time notification sent successfully.");
// } catch (error) {
// console.error("Error sending thresmanual method time notification:", error);
// }
// });
// Function to emit events with timestamps
const emitWithTimestamp = (eventName, fcmTokens, motorId, waterLevel) => {
const timestamp = moment().format('HH:mm:ss YYYY-MM-DD ');
eventEmitter.emit(eventName, fcmTokens, timestamp, motorId, waterLevel);
};
// const sendNotification = async (fcmTokens, title, body) => {
// if (!Array.isArray(fcmTokens) || fcmTokens.length === 0) {
// console.error('No FCM tokens provided.');
// return;
// }
// for (const token of fcmTokens) {
// const message = {
// token: token,
// notification: {
// title: title,
// body: body,
// },
// data: {
// target: 'tank_levels',
// },
// };
// try {
// const response = await admin.messaging().send(message); // Send each message individually
// console.log('Notification sent successfully:', response);
// } catch (error) {
// console.error(`Failed to send notification to token ${token}:`, error);
// }
// }
// };
// const sendNotification = async (fcmIds, title, body) => {
// try {
// if (!fcmIds || fcmIds.length === 0) {
// throw new Error('No FCM tokens provided.');
// }
// const flatTokens = fcmIds.flat();
// if (flatTokens.length === 0) {
// throw new Error('Flattened FCM token list is empty.');
// }
// // Iterate over each token and send individually
// const promises = flatTokens.map(async (token) => {
// try {
// const response = await admin.messaging().send({
// notification: { title, body },
// token,
// data: {
// 'target': 'tank_levels',
// },
// });
// 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}`);
// }
// }
// });
// await Promise.all(promises);
// } catch (error) {
// console.error('Error sending notifications:', error);
// }
// };
// const sendNotification = async (customerId, fcmIds, title, body) => {
// try {
// if (!customerId) {
// throw new Error("Customer ID is required.");
// }
// if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
// throw new Error("No FCM tokens provided or invalid format.");
// }
// // Safely flatten the tokens
// const flatTokens = fcmIds.flat ? fcmIds.flat() : fcmIds; // Use flat() if available
// if (flatTokens.length === 0) {
// throw new Error("Flattened FCM token list is empty.");
// }
// // Fetch user notification settings
// const users = await User.find({ customerId }).select("fcmIds notificationPreference lastNotificationSent");
// // Iterate over users to send notifications based on their preferences
// const promises = users.map(async (user) => {
// const { fcmIds: userFcmIds, notificationPreference, lastNotificationSent } = user;
// // Check if userFcmIds is an array
// if (!Array.isArray(userFcmIds)) {
// console.log(`Invalid fcmIds for customer ID: ${customerId}`);
// return;
// }
// // Filter tokens that belong to the user
// const validTokens = flatTokens.filter(token => userFcmIds.includes(token));
// if (validTokens.length === 0) {
// console.log(`No matching FCM tokens for customer ID: ${customerId}`);
// return;
// }
// // // Handle notification preference
// // if (notificationPreference === "never") {
// // console.log(`Notifications disabled for customer ID: ${customerId}`);
// // return;
// // }
// const now = new Date();
// const lastSent = new Date(lastNotificationSent || 0);
// // If preference is not "always", check the timing
// // if (notificationPreference !== "always") {
// // let minInterval = 0;
// // switch (notificationPreference) {
// // case "6_hours":
// // minInterval = 6 * 60 * 60 * 1000; // 6 hours
// // break;
// // case "8_hours":
// // minInterval = 8 * 60 * 60 * 1000; // 8 hours
// // break;
// // case "1_month":
// // minInterval = 30 * 24 * 60 * 60 * 1000; // 1 month
// // break;
// // }
// // // Skip sending if the time restriction hasn't passed
// // if (now - lastSent < minInterval) {
// // console.log(`Skipping notification for customer ID: ${customerId} due to time restriction.`);
// // return;
// // }
// // }
// // Send notifications
// const notificationPromises = flatTokens.map(async (token) => {
// try {
// const response = await admin.messaging().send({
// notification: { title, body },
// token,
// data: { target: "/tank_levels" },
// });
// console.log(`Notification sent successfully to token: ${token}`);
// console.log("FCM Response:", response); // Log the full response
// console.log(`Title: ${title}, Body: ${body}`); // Log title and body before sending
// } catch (error) {
// console.error(`Failed to send notification to token: ${token}`, error);
// // Handle token errors
// if (error.code === "messaging/registration-token-not-registered") {
// await User.updateOne(
// { customerId },
// { $pull: { fcmIds: token } } // Remove invalid token
// );
// console.log(`Removed invalid token: ${token}`);
// }
// }
// });
// await Promise.all(notificationPromises);
// // Update lastNotificationSent timestamp if not "always"
// if (notificationPreference !== "always") {
// await User.updateOne({ customerId }, { lastNotificationSent: now });
// }
// });
// await Promise.all(promises);
// } catch (error) {
// console.error("Error sending notifications:", error);
// }
// };
// important
// const sendNotification = async (customerId, fcmIds, title, body) => {
// try {
// if (!customerId) {
// throw new Error("Customer ID is required.");
// }
// if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
// console.log("No valid FCM tokens provided.");
// return;
// }
// // Flatten nested arrays
// const flatFcmIds = fcmIds.flat();
// // Fetch user from database
// const user = await User.findOne({ customerId }).select("fcmIds");
// if (!user || !Array.isArray(user.fcmIds)) {
// console.log(`No valid FCM tokens found for customer ID: ${customerId}`);
// return;
// }
// console.log("User's stored FCM tokens:", user.fcmIds);
// console.log("FCM tokens passed to function:", flatFcmIds);
// // Proper token filtering
// const validTokens = user.fcmIds.filter(token => flatFcmIds.some(t => t.trim() === token.trim()));
// console.log("Valid tokens for notification:", validTokens);
// if (validTokens.length === 0) {
// console.log(`No matching FCM tokens for customer ID: ${customerId}`);
// return;
// }
// const promises = validTokens.map(async (token) => {
// try {
// console.log(`Sending notification to token: ${token}`);
// const response = await admin.messaging().send({
// notification: { title, body },
// token,
// data: { target: "/tank_levels" },
// });
// console.log(`Notification sent successfully:`, response);
// console.log(`title:`, title);
// console.log(`body:`, body);
// } catch (error) {
// console.error(`Failed to send notification to token: ${token}`, error);
// if (error?.errorInfo?.code === "messaging/registration-token-not-registered") {
// await User.updateOne({ customerId }, { $pull: { fcmIds: token } });
// console.log(`Removed invalid token: ${token}`);
// }
// }
// });
// await Promise.all(promises);
// } catch (error) {
// console.error("Error sending notifications:", error);
// }
// };
const sendNotification = async (hw_Id, customerId, fcmIds, title, body) => {
try {
if (!customerId) throw new Error("Customer ID is required.");
if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
throw new Error("No FCM tokens provided or invalid format.");
}
const flatTokens = fcmIds.flat ? fcmIds.flat() : fcmIds;
if (flatTokens.length === 0) throw new Error("Flattened FCM token list is empty.");
console.log(`📨 Preparing to send notification to Customer ID: ${customerId}`);
// Fetch users with FCM tokens & preferences
const users = await User.find({ customerId }).select("fcmIds notificationPreference lastNotificationSent");
const promises = users.map(async (user) => {
const { fcmIds: userFcmIds, notificationPreference, lastNotificationSent } = user;
if (!Array.isArray(userFcmIds)) return console.log(`⚠️ Invalid fcmIds for customer ID: ${customerId}`);
const validTokens = flatTokens.filter(token => userFcmIds.includes(token));
if (validTokens.length === 0) return console.log(`⚠️ No matching FCM tokens for customer ID: ${customerId}`);
// Handle notification preferences
if (notificationPreference === "never") return console.log(`🔕 Notifications disabled for Customer ID: ${customerId}`);
const now = new Date();
const lastSent = new Date(lastNotificationSent || 0);
let minInterval = 0;
switch (notificationPreference) {
case "6_hours":
minInterval = 6 * 60 * 60 * 1000;
break;
case "8_hours":
minInterval = 8 * 60 * 60 * 1000;
break;
case "1_month":
minInterval = 30 * 24 * 60 * 60 * 1000;
break;
}
if (notificationPreference !== "always" && now - lastSent < minInterval) {
return console.log(`⏳ Skipping notification for Customer ID: ${customerId} due to preference (${notificationPreference}).`);
}
console.log(`🚀 Sending notification to Customer ID: ${customerId}, Tokens: ${validTokens.length}`);
const notificationPromises = validTokens.map(async (token) => {
try {
const response = await admin.messaging().send({
token,
notification: { title, body },
data: {
hw_Id: String(hw_Id),
target: "/tank_levels"
},
});
console.log(`✅ Notification sent successfully to token: ${token}`);
console.log("📬 FCM Response:", response);
console.log(`📡 Sending notification to Customer ID: ${customerId}`);
//console.log(`🔍 FCM Tokens:`, fcmTokens);
} catch (error) {
// console.error(`❌ Failed to send notification to token: ${token}`, error);
if (error.code === "messaging/registration-token-not-registered") {
await User.updateOne({ customerId }, { $pull: { fcmIds: token } });
console.log(`🗑️ Removed invalid token: ${token}`);
}
}
});
await Promise.all(notificationPromises);
if (notificationPreference !== "always") {
await User.updateOne({ customerId }, { $set: { lastNotificationSent: now } });
}
});
await Promise.all(promises);
} catch (error) {
console.error("❌ Error sending notifications:", error);
}
};
// Function to send notifications
const sendDailyConsumptionNotification = async () => {
try {
const now = new Date();
const currentTime = moment(now).format("HH:mm"); // e.g., "09:30"
const currentDate = moment(now).format("DD-MMM-YYYY"); // e.g., "28-Feb-2025"
console.log(`🕒 Checking users for scheduled notifications at ${currentTime}`);
// Fetch unique users who have enabled notifications for the current time
const users = await User.find({
allowNotifications: true,
notificationTime: currentTime,
}).select("customerId fcmIds lastNotificationSent").lean();
// Ensure unique customers only
const uniqueUsers = users.filter((user, index, self) =>
index === self.findIndex((u) => u.customerId === user.customerId)
);
if (uniqueUsers.length === 0) {
console.log("⏳ No users have notifications scheduled for this time.");
return;
}
for (const user of uniqueUsers) {
const { customerId, fcmIds, lastNotificationSent } = user;
// Ensure user has valid FCM tokens
if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
console.log(`⚠️ No valid FCM tokens for customer ID: ${customerId}`);
continue;
}
// Remove duplicate and trim tokens
const uniqueTokens = [...new Set(fcmIds.map(token => token.trim()))];
// Check if notification should be sent based on lastNotificationSent
const lastSent = new Date(lastNotificationSent || 0);
if (now - lastSent < 24 * 60 * 60 * 1000) {
console.log(`⏳ Skipping notification for ${customerId}, already sent in the last 24 hours.`);
continue;
}
// Fetch last 24-hour consumption data
const startTime = moment(now).subtract(1, "days").format("DD-MMM-YYYY - HH:mm");
const endTime = moment(now).format("DD-MMM-YYYY - HH:mm");
console.log(`📅 Fetching consumption for ${customerId} from ${startTime} to ${endTime}`);
const consumptions = await TankConsumptionOriginalSchema.find({
customerId,
time: { $gte: startTime, $lt: endTime },
});
if (consumptions.length === 0) {
console.log(`❌ No consumption data found for ${customerId}`);
continue;
}
// Standardized mapping for water types
const typeMapping = {
"bore water": "Bore Water",
"bore": "Bore Water",
"drinking": "Drinking Water",
"drink": "Drinking Water",
"DRINK": "Drinking Water"
};
// Calculate consumption per water type
let totalConsumption = 0;
let consumptionByType = {};
for (const record of consumptions) {
let { typeofwater, consumption } = record;
typeofwater = (typeofwater || "").trim().toLowerCase(); // Normalize case
const standardType = typeMapping[typeofwater] || typeofwater; // Use mapped name or original
const consumptionValue = parseInt(consumption, 10) || 0;
if (!consumptionByType[standardType]) {
consumptionByType[standardType] = 0;
}
consumptionByType[standardType] += consumptionValue;
totalConsumption += consumptionValue;
}
// Prepare notification message
let notificationBody = `🚰 Water Consumption Report for ${currentDate}:\n`;
for (const type in consumptionByType) {
const percentage = totalConsumption ? ((consumptionByType[type] / totalConsumption) * 100).toFixed(2) : 0;
notificationBody += `\n💧 Type: ${type}\n` +
`Total Consumption: ${consumptionByType[type]} liters (${percentage}%)\n`;
}
console.log(`📩 Preparing notification for ${customerId}:`, notificationBody);
// Update lastNotificationSent before sending
await User.updateOne(
{ customerId },
{ $set: { lastNotificationSent: new Date() } }
);
// Send notification to FCM tokens
const notificationPromises = uniqueTokens.map(async (token) => {
try {
await admin.messaging().send({
notification: { title: "Daily Water Consumption Report", body: notificationBody },
token,
data: { target: "/tank_levels" },
});
console.log(`✅ Notification sent to token: ${token}`);
} catch (error) {
console.error(`❌ Failed to send notification to token: ${token}`, error);
if (error.code === "messaging/registration-token-not-registered") {
await User.updateOne({ customerId }, { $pull: { fcmIds: token } });
console.log(`🚫 Removed invalid token: ${token}`);
}
}
});
await Promise.all(notificationPromises);
}
} catch (error) {
console.error("❌ Error sending daily consumption notifications:", error);
}
};
cron.schedule("* * * * *", async () => {
console.log("🔄 Running daily consumption notification check...");
await sendDailyConsumptionNotification();
}, {
timezone: "Asia/Kolkata",
});
// const sendPushNotification = async (registrationToken, title, body) => {
// const message = {
// notification: {
// title: title,
// body: body,
// },
// data: {
// title: title,
// body: body,
// },
// };
// const options = {
// priority: "high",
// timeToLive: 60 * 60 * 24,
// };
// try {
// const response = await admin.messaging().sendToDevice(registrationToken, message, options);
// console.log('FCM response:', response); // Log the FCM response
// return response; // Return the FCM response object
// } catch (error) {
// console.error('FCM error:', error);
// throw error; // Throw the error to handle it further up the call stack
// }
// };
exports.publishMotorStopStatus = async (motor_id, motor_stop_status) => {
// console.log("entered publish",motor_id,motor_stop_status)
const deviceTopic = `water/operation/${motor_id}`; // Target specific IoT
//console.log(deviceTopic,"deviceTopic")
const payload = {
topic: 'operation',
object: {
'motor-id': motor_id,
control: motor_stop_status
}
};
//console.log(`📡 Publishing to ${deviceTopic}`);
console.log(payload);
// Publish to the specific device's control topic
client.publish(deviceTopic, JSON.stringify(payload));
};
const stat_stop_intervals = {};
// exports.motorAction = async (req, reply) => {
// try {
// const customerId = req.params.customerId;
// const action = req.body.action;
// const motorId = req.body.motor_id;
// const start_instance_id = req.body.start_instance_id
// console.log(req.body.startTime)
// // Ensure motor_id is provided
// if (!motorId) {
// throw new Error("Motor ID is required.");
// }
// const users = await User.find({ customerId: customerId });
// const fcmToken = users.map(user => user.fcmId).filter(fcmId => fcmId);
// console.log(fcmToken)
// // Determine the motor stop status based on the action
// let motorStopStatus;
// if (action === "start") {
// motorStopStatus = "2"; // If action is start, set stop status to "2"
// // eventEmitter.emit('motorStart', fcmToken); // Emit motor start event
// emitWithTimestamp('motorStart', fcmToken); // Emit motor start event with timestamp
// console.log( eventEmitter.emit('motorStart', fcmToken))
// } else if (action === "stop") {
// motorStopStatus = "1"; // If action is stop, set stop status to "1"
// // eventEmitter.emit('motorStop', fcmToken); // Emit motor stop event
// emitWithTimestamp('motorStop', fcmToken); // Emit motor stop event with timestamp
// } else {
// throw new Error("Invalid action provided.");
// }
// // Update the motor stop status immediately if action is stop
// if (action === "stop") {
// // Update the motor stop status and other fields
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.stopTime": req.body.stopTime,
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// reply.code(200).send({ message: "Motor stopped successfully." });
// // Perform stop operations in the background
// (async () => {
// await delay(300000);
// // Update the existing motor data entry with stop details
// 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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
// const totalwaterpumped = quantityDelivered + water_pumped_till_now;
// await Tank.findOneAndUpdate(
// { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
// { $set: { total_water_added_from_midnight: totalwaterpumped } }
// );
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime: req.body.stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// })();
// // Return here to ensure the rest of the code is not executed for the stop action
// return;
// } else {
// // Update the motor stop status to "2" for start action
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
// );
// }
// // Check threshold settings if action is start
// if (action === "start") {
// if (req.body.threshold_type === "time") {
// // If threshold type is time, update threshold time
// // await Tank.updateOne(
// // { customerId, "connections.inputConnections.motor_id": motorId },
// // { $set: { "connections.inputConnections.$.manual_threshold_time": req.body.manual_threshold_time,startTime:req.body.startTime } }
// // );
// const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const newMotorData = new MotorData({
// customerId: customerId,
// motor_id: motorId,
// start_instance_id: start_instance_id,
// supplierTank: req.body.from,
// receiverTank: req.body.to,
// supplier_type: req.body.from_type,
// receiver_type: req.body.to_type,
// startTime: req.body.startTime,
// receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
// });
// await newMotorData.save();
// for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
// const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
// if (index !== -1) {
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime,[`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
// );
// }
// }
// // Start monitoring water level based on threshold time
// const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
// const intervalId = setInterval(async () => {
// const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
// //console.log(splr_tank_info3_waterlevel,"splr_tank_info3_waterlevel")
// const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
// // const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity, 10);
// // console.log(splr_tank_info3.capacity,splr_tank_info3_capacity,"splr_tank_info3_capacity")
// const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;
// // console.log(splr_tank_info3_percentage, "percentage for less than 20");
// if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
// console.log(splr_tank_info3_percentage,)
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// clearInterval(intervalId);
// await delay(300000);
// 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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
// const totalwaterpumped = quantityDelivered + water_pumped_till_now
// await Tank.findOneAndUpdate({customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase()}, { $set: { total_water_added_from_midnight: totalwaterpumped } })
// const stopTime = formatDate(new Date());
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime:stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// }
// }, 60000);
// } else if (req.body.threshold_type === "litres") {
// console.log("entered litres")
// const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const newMotorData = new MotorData({
// customerId: customerId,
// motor_id: motorId,
// start_instance_id: start_instance_id,
// supplierTank: req.body.from,
// receiverTank: req.body.to,
// supplier_type: req.body.from_type,
// receiver_type: req.body.to_type,
// startTime: req.body.startTime,
// receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
// });
// await newMotorData.save();
// // If threshold type is percentage, calculate percentage threshold
// const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// if (!receiver_tank_info) {
// throw new Error("Receiver tank not found.");
// }
// if (!supplier_tank_info) {
// throw new Error("Supplierr tank not found.");
// }
// const supplier_capacity = parseInt(supplier_tank_info.capacity, 10);
// const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10);
// const capacity = parseInt(receiver_tank_info.capacity, 10);
// const waterLevel = parseInt(receiver_tank_info.waterlevel, 10);
// const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);
// console.log(desired_percentage)
// const threshold_water_level = waterLevel+desired_percentage;
// const supplier_threshold = supplier_waterLevel-desired_percentage
// console.log(supplier_threshold,"supplier_threshold")
// for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
// const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
// if (index !== -1) {
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
// );
// }
// }
// // Update water level threshold
// // Start monitoring water level based on threshold percentage
// const intervalId = setInterval(async () => {
// // Check if water level has reached the threshold percentage
// const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
// if (current_water_level <= supplier_threshold) {
// // Stop the motor pump
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// clearInterval(intervalId); // Stop monitoring water level
// await delay(300000);
// 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 stopTime = formatDate(new Date());
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime:stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// }
// }, 20000); // Check water level every minute
// }
// }
// // Respond with success message
// reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
// } catch (err) {
// // Handle errors
// throw boom.boomify(err);
// }
// };
const notificationSentStatus = {
motorStart: false,
motorStop: false,
lowWater: false,
veryLowWater: false,
criticallyLowWater: false,
highWater: false,
veryHighWater: false,
criticallyHighWater: false,
};
let waterLevelCheckInterval; // To hold the interval ID
exports.getPumpsAndUsers = async (req, reply) => {
try {
const { customerId } = req.params;
// Fetch motor_id from inputConnections of all tanks for the customer
const tanks = await Tank.find({ customerId }, { "connections.inputConnections.motor_id": 1 });
const motorIds = tanks.flatMap((tank) =>
tank.connections?.inputConnections?.map((conn) => conn.motor_id).filter(Boolean) || []
);
// Fetch username and staff names from User collection
const user = await User.findOne({ customerId }, { username: 1, "staff.staff.name": 1 });
const staffNames = user?.staff?.staff?.map((s) => s.name) || [];
const username = user?.username || "";
// Include username at the beginning of staffNames and add "manual" at the end
const updatedStaffNames = ["All",username, ...staffNames, "manual","user"];
const updatedmotorIds = ["All",...motorIds];
// Prepare response
const result = {
motorIds: updatedmotorIds,
staffNames: updatedStaffNames,
};
return reply.send({ success: true, data: result });
} catch (error) {
console.error("Error fetching data:", error);
return reply.status(500).send({ success: false, message: "Internal Server Error" });
}
};
exports.motoractiontest = async (req, reply) => {
try {
const { customerId } = req.params;
const { motor_id, action } = req.body;
// Fetch Tank data using customerId
const customer = await Tank.findOne({ customerId });
// console.log("Customer Data:", customer);
if (!customer) {
return reply.status(404).send({ success: false, message: "Customer not found" });
}
let motorFound = false;
// Traverse through inputConnections instead of tanks.inputconnections
for (const inputConnection of customer.connections.inputConnections || []) {
console.log("Checking Motor ID:", inputConnection.motor_id);
if (String(inputConnection.motor_id) === String(motor_id)) { // Convert both to string
motorFound = true;
if (action === "start") {
await this.publishMotorStopStatus(motor_id, "2");
} else if (action === "stop") {
await this.publishMotorStopStatus(motor_id, "1");
} else {
return reply.status(400).send({ success: false, message: "Invalid action" });
}
return reply.send({ success: true, message: `Motor ${action} command sent.` });
}
}
if (!motorFound) {
return reply.status(404).send({ success: false, message: "Motor ID not found" });
}
} catch (error) {
console.error("Error fetching data:", error);
return reply.status(500).send({ success: false, message: "Internal Server Error" });
}
};
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;
const { action, motor_id: motorId, start_instance_id, phone, threshold_type, manual_threshold_time, manual_threshold_litres } = req.body;
if (!motorId) throw new Error("Motor ID is required.");
const users = await User.findOne({ customerId });
if (!users) return reply.status(404).send({ error: "User not found" });
let loggedInUser = users.phone === phone ?
{ role: "Customer", name: users.username, phone: users.phone } :
users.staff?.staff?.find(staff => staff.phone === phone) ?
{ role: "Staff", name: users.staff.staff.find(staff => staff.phone === phone).name, phone } : null;
if (!loggedInUser) return reply.status(404).send({ error: "User not found" });
console.log(loggedInUser)
const fcmToken = users.fcmIds ? users.fcmIds.filter(id => id) : [];
const receiverTank = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
if (!receiverTank) throw new Error("Receiver tank not found.");
const typeOfWater = receiverTank.typeOfWater;
let motorStopStatus = action === "start" ? "2" : "1";
const blockName = req.body.from || "Unknown Block";
const tankName = req.body.to || "Unknown Tank";
const stopTime = req.body.stopTime
const inputConnection_1 = receiverTank.connections?.inputConnections?.find(
conn => conn.motor_id === motorId
);
// Step 2: Check motor_stop_status
if (action === "start" && inputConnection_1.motor_stop_status === "2") {
// ✅ Proceed with motor start logic
return reply.status(400).send({ error: "Motor is already running or blocked from starting." });
// ... your logic to handle starting the motor
}
if (action === "start" && inputConnection_1.motor_stop_status !== "2") {
if (motorIntervals[motorId]) {
console.log(`🛑 Clearing old interval for motorId: ${motorId}`);
clearInterval(motorIntervals[motorId]);
delete motorIntervals[motorId];
// Confirm deletion
if (!motorIntervals[motorId]) {
console.log(`✅ Old interval successfully deleted.`);
} else {
console.error(`❌ Failed to delete old interval.`);
}
}
const startTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{ $set: {
"connections.inputConnections.$.motor_stop_status": "2",
"connections.inputConnections.$.threshold_type": threshold_type,
"connections.inputConnections.$.motor_on_type": "manual"
}}
);
eventEmitter.emit("motorStart", customerId, fcmToken, tankName, blockName, startTime, "Mobile APP", manual_threshold_time, typeOfWater, motorId, loggedInUser.phone);
//this.publishMotorStopStatus(motorId, motorStopStatus);
reply.code(200).send({ message: "Motor started successfully." });
if (req.body.threshold_type === "time") {
// Create a new MotorData entry
const receiverTank = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
const newMotorData = new MotorData({
customerId,
motor_id: motorId,
start_instance_id: start_instance_id,
supplierTank: req.body.from,
receiverTank: req.body.to,
supplier_type: req.body.from_type,
receiver_type: req.body.to_type,
startTime: req.body.startTime,
receiverInitialwaterlevel: parseInt(receiverTank.waterlevel, 10),
started_by:loggedInUser.name
});
await newMotorData.save();
console.log("entered time",motorId,motorStopStatus)
// Update the tank connections with start time and threshold time
this.publishMotorStopStatus(motorId, motorStopStatus);
const startTime1 = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm:ss');
for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
if (index !== -1) {
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{
$set: {
[`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time,
[`connections.inputConnections.${index}.threshold_type`]: "time",
[`connections.inputConnections.${index}.startTime`]: startTime1,
[`connections.inputConnections.${index}.start_instance_id`]: start_instance_id
}
}
);
}
}
const thresholdTime = new Date(new Date().getTime() + req.body.manual_threshold_time * 60000);
console.log("New Threshold Time:", thresholdTime);
console.log("Current Time:", new Date());
motorIntervals[motorId] = setInterval(async () => {
console.log(motorId,"interval created")
console.log(customerId,req.body.from,req.body.from_type.toLowerCase())
const supplierTank = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
console.log("up",supplierTank)
console.log(supplierTank.waterlevel,"parseInt(supplierTank.waterlevel, 10)")
const lowWaterThreshold = 20;
const currentWaterLevel = parseInt(supplierTank.waterlevel, 10);
const currentWaterPercentage = (currentWaterLevel / parseInt(supplierTank.capacity.replace(/,/g, ''), 10)) * 100;
const notificationTracker = new Map();
if (new Date() >= thresholdTime || currentWaterPercentage <= lowWaterThreshold) {
console.log(new Date(),"new date")
console.log(thresholdTime,"thresholdTime")
console.log("motor stopping because it entered this condition")
// Emit the threshold time notification
try {
console.log("motor stopping because it entered this condition")
const tank = await Tank.findOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{ "connections.inputConnections.$": 1 } // Fetch only relevant motor connection
);
if (tank && tank.connections.inputConnections[0].motor_stop_status === "1") {
console.log("⚠️ Motor already stopped. Skipping notification.");
} else {
console.log("🚀 Sending threshold time notification...");
eventEmitter.emit(
"sendThresholdTimeNotification",
customerId,
fcmToken,
manual_threshold_time,
motorId,
tankName,
blockName
);
}
reply.code(200).send({ message: "Motor stopped successfully." });
} catch (error) {
console.error("Error in handleMotorStop:", error);
reply.code(500).send({ error: "Internal Server Error" });
}
const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
const currentTime1 = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm:ss');
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{
$set: {
"connections.inputConnections.$.motor_stop_status": "1",
"connections.inputConnections.$.start_instance_id": null,
"connections.inputConnections.$.threshold_type": null,
"connections.inputConnections.$.manual_threshold_time": null,
"connections.inputConnections.$.manual_threshold_percentage": null,
"connections.inputConnections.$.stopTime": currentTime1,
}
}
);
if (motorIntervals[motorId]) {
console.log(`🛑 Clearing interval for motorId: ${motorId}`);
clearInterval(motorIntervals[motorId]);
delete motorIntervals[motorId];
// Confirm deletion
if (!motorIntervals[motorId]) {
console.log(`✅ Interval for motorId: ${motorId} successfully deleted.`);
} else {
console.error(`❌ Failed to delete interval for motorId: ${motorId}`);
}
}
this.publishMotorStopStatus(motorId, "1");
console.log(start_instance_id,"start_instance_id",customerId,"customerId",motorId,"motorId")
const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
console.log(motorData,"motorData")
if (motorData) {
console.log("got into if")
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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
const totalwaterpumped = quantityDelivered + water_pumped_till_now;
const start = moment(motorData.startTime, 'DD-MMM-YYYY - HH:mm');
const stop = moment(currentTime, 'DD-MMM-YYYY - HH:mm');
const duration = moment.duration(stop.diff(start));
const runtime = Math.floor(duration.asMinutes()); // runtime in minutes
await Tank.findOneAndUpdate(
{ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
{ $set: { total_water_added_from_midnight: totalwaterpumped } }
);
await MotorData.updateOne(
{ customerId, motor_id: motorId, start_instance_id: start_instance_id },
{
$set: {
stopTime: currentTime,
receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
quantity_delivered: quantityDelivered.toString(),
runtime: runtime.toString(),
stopped_by:loggedInUser.name
}
}
);
}
}
// Check for high water level and send notification
// if (currentWaterPercentage >= highWaterThreshold) {
// // eventEmitter.emit('sendHighWaterNotification', fcmToken, receiverTank);
// await checkWaterLevelsAndNotify(customerId, tankName, supplierTank.tankLocation, fcmToken);
// }
}, 30000); // Check every minute
}
else if (req.body.threshold_type === "litres") {
console.log("entered litres")
const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
const supplier_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
const newMotorData = new MotorData({
customerId: customerId,
motor_id: motorId,
start_instance_id: start_instance_id,
supplierTank: req.body.from,
receiverTank: req.body.to,
supplier_type: req.body.from_type,
receiver_type: req.body.to_type,
startTime: req.body.startTime,
receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10),
supplierInitialwaterlevel:parseInt(supplier_tank_info7.waterlevel, 10),
started_by:loggedInUser.name
});
await newMotorData.save();
// If threshold type is percentage, calculate percentage threshold
const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
if (!receiver_tank_info) {
throw new Error("Receiver tank not found.");
}
if (!supplier_tank_info) {
throw new Error("Supplierr tank not found.");
}
const supplier_capacity = parseInt(supplier_tank_info.capacity, 10);
const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10);
const capacity = parseInt(receiver_tank_info.capacity, 10);
const waterLevel = parseInt(receiver_tank_info.waterlevel, 10);
const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);
console.log(desired_percentage)
const threshold_water_level = waterLevel+desired_percentage;
const supplier_threshold = supplier_waterLevel-desired_percentage
console.log(supplier_threshold,"supplier_threshold")
for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
this.publishMotorStopStatus(motorId, motorStopStatus);
for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
if (index !== -1) {
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{ $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
);
}
}
// Update water level threshold
// Start monitoring water level based on threshold percentage
motorIntervals[motorId] = setInterval(async () => {
// Check if water level has reached the threshold percentage
const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
if (current_water_level <= supplier_threshold) {
// Stop the motor pump
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{
$set: {
"connections.inputConnections.$.motor_stop_status": "1",
"connections.inputConnections.$.start_instance_id": null,
"connections.inputConnections.$.threshold_type": null,
"connections.inputConnections.$.manual_threshold_time": null,
"connections.inputConnections.$.manual_threshold_percentage": null
}
}
);
clearInterval(motorIntervals[motorId]); // Clear interval
delete motorIntervals[motorId];
this.publishMotorStopStatus(motorId, "1");
await delay(300000);
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 stopTime = formatDate(new Date());
await MotorData.updateOne(
{ customerId, motor_id: motorId, start_instance_id: start_instance_id },
{
$set: {
stopTime:stopTime,
receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
quantity_delivered: quantityDelivered.toString(),
stopped_by:loggedInUser.name
}
}
);
}
}
}, 20000);
}
}
} else if (action === "stop") {
// Dynamically find start_instance_id from tank
const tankWithMotor = await Tank.findOne({
customerId,
"connections.inputConnections.motor_id": motorId
});
let dynamicInstanceId = null;
let user_name = loggedInUser.name
console.log(user_name,"user_name in stop1")
if (tankWithMotor) {
const connection = tankWithMotor.connections.inputConnections.find(conn => conn.motor_id === motorId);
if (connection && connection.start_instance_id) {
dynamicInstanceId = connection.start_instance_id;
}
}
await stopMotor(motorId, customerId, dynamicInstanceId,user_name);
try {
const motorData = await MotorData.findOne({
customerId,
motor_id: motorId,
start_instance_id: dynamicInstanceId
});
let totalWaterPumped = 0; // Default value in case data is missing
if (motorData && motorData.quantity_delivered) {
totalWaterPumped = motorData.quantity_delivered;
}
console.log("quantity_delivered:", totalWaterPumped);
//const totalWaterPumped = await motorData.quantity_delivered
// console.log("quantity_delivered",totalWaterPumped)
eventEmitter.emit("motorStop", customerId, fcmToken, tankName, blockName, stopTime, "Mobile APP", totalWaterPumped, typeOfWater, motorId,
loggedInUser.phone,);
reply.code(200).send({ message: "Motor stopped successfully." });
} catch (error) {
console.error("Error in handleMotorStop:", error);
reply.code(500).send({ error: "Internal Server Error" });
}
this.publishMotorStopStatus(motorId, motorStopStatus);
reply.code(200).send({ message: "Motor stopped successfully." });
}
} catch (err) {
throw boom.boomify(err);
}
};
async function stopMotor(motorId, customerId, start_instance_id,user_name) {
console.log(user_name,"user_name in stop2")
const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
const currentTime1 = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm:ss');
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{ $set: {
"connections.inputConnections.$.motor_stop_status": "1",
"connections.inputConnections.$.stopTime": currentTime1,
"connections.inputConnections.$.start_instance_id": null,
"connections.inputConnections.$.threshold_type": null,
"connections.inputConnections.$.manual_threshold_time": null,
"connections.inputConnections.$.manual_threshold_percentage": null
}}
);
if (motorIntervals[motorId]) {
clearInterval(motorIntervals[motorId]);
delete motorIntervals[motorId];
}
// eventEmitter.emit("motorStop", customerId, [], "", "", currentTime, "Mobile APP", 0, "", motorId, "");
const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id });
if (motorData) {
const start = moment(motorData.startTime, 'DD-MMM-YYYY - HH:mm');
const stop = moment(currentTime, 'DD-MMM-YYYY - HH:mm');
const duration = moment.duration(stop.diff(start));
const runtime = Math.floor(duration.asMinutes()); // runtime in minutes
const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel.replace(/,/g, ''), 10);
const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel.replace(/,/g, ''), 10);
await MotorData.updateOne(
{ customerId, motor_id: motorId, start_instance_id },
{ $set: { stopTime: currentTime, receiverfinalwaterlevel: receiverFinalWaterLevel.toString(), quantity_delivered: quantityDelivered.toString(), runtime: runtime,stopped_by:user_name } }
);
}
}
const monitorWaterLevels = async () => {
try {
// console.log("⏳ Monitoring water levels...");
const tanks = await Tank.find(); // Fetch all tanks
//console.log("Fetched Tanks:", tanks.length);
for (const tank of tanks) {
const {
_id,
customerId, // Move this to the top
motor_id,
tankName,
blockName,
waterlevel: currentWaterLevel,
capacity,
auto_min_percentage,
reserved_percentage,
notificationSentLow,
notificationSentCritical,
} = tank;
const users = await User.find({ customerId });
const fcmTokens = users
.map(user => user.fcmIds)
.filter(fcmIds => Array.isArray(fcmIds) && fcmIds.length > 0) // Ensure it's an array
.flat();
if (!fcmTokens || fcmTokens.length === 0) {
//console.error("❌ No valid FCM tokens found for customerId:", customerId);
continue; // Skip this tank
}
const LOW_PERCENTAGE = 20; // 20% threshold
const CRITICAL_PERCENTAGE = 10; // 10% threshold
// **Calculate thresholds based on tank capacity**
const lowWaterLevel = (LOW_PERCENTAGE / 100) * capacity;
const criticalLowWaterLevel = (CRITICAL_PERCENTAGE / 100) * capacity;
const currentWaterPercentage = (currentWaterLevel / capacity) * 100;
// const lowWaterLevel = 9483; // Low threshold in liters
// const criticalLowWaterLevel = 9483;
if (currentWaterLevel <= criticalLowWaterLevel) {
if (!notificationSentCritical) {
console.log("🚨 Sending Critical Low Water Notification...");
eventEmitter.emit("sendCriticalLowWaterNotification", customerId, fcmTokens, motor_id, tankName, blockName, criticalLowWaterLevel, currentWaterLevel, currentWaterPercentage);
await Tank.updateOne({ _id }, { notificationSentCritical: true, notificationSentLow: true });
}
}
else if (currentWaterLevel <= lowWaterLevel) {
if (!notificationSentLow) {
console.log("⚠️ Sending Low Water Notification...");
eventEmitter.emit("sendLowWaterNotification", customerId, fcmTokens, motor_id, tankName, blockName, lowWaterLevel, currentWaterLevel, currentWaterPercentage);
await Tank.updateOne({ _id }, { notificationSentLow: true });
}
}
else if (currentWaterLevel > lowWaterLevel && (notificationSentLow || notificationSentCritical)) {
console.log("🔄 Water level restored. Resetting flags.");
await Tank.updateOne({ _id }, { notificationSentCritical: false, notificationSentLow: false });
}
}
} catch (error) {
console.error("❌ Error monitoring water levels:", error);
}
};
setInterval(monitorWaterLevels, 1000);
// async function stopMotor(motorId, customerId, start_instance_id) {
// const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.stopTime": currentTime,
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }}
// );
// if (motorIntervals[motorId]) {
// clearInterval(motorIntervals[motorId]);
// delete motorIntervals[motorId];
// }
// eventEmitter.emit("motorStop", customerId, [], "", "", currentTime, "Mobile APP", 0, "", motorId, "");
// const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id });
// if (motorData) {
// const startTime = moment(motorData.startTime, 'DD-MMM-YYYY - HH:mm');
// const runtime = moment.duration(moment(currentTime, 'DD-MMM-YYYY - HH:mm').diff(startTime)).asSeconds();
// const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
// const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel.replace(/,/g, ''), 10);
// const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel.replace(/,/g, ''), 10);
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id },
// { $set: { stopTime: currentTime, receiverfinalwaterlevel: receiverFinalWaterLevel.toString(), quantity_delivered: quantityDelivered.toString(), runtime: runtime } }
// );
// }
// }
// exports.motorAction = async (req, reply) => {
// try {
// const customerId = req.params.customerId;
// const action = req.body.action;
// const motorId = req.body.motor_id;
// const start_instance_id = req.body.start_instance_id
// console.log(req.body.startTime)
// // Ensure motor_id is provided
// if (!motorId) {
// throw new Error("Motor ID is required.");
// }
// // Determine the motor stop status based on the action
// let motorStopStatus;
// if (action === "start") {
// motorStopStatus = "2"; // If action is start, set stop status to "2"
// } else if (action === "stop") {
// motorStopStatus = "1"; // If action is stop, set stop status to "1"
// } else {
// throw new Error("Invalid action provided.");
// }
// // Update the motor stop status immediately if action is stop
// if (action === "stop") {
// // Update the motor stop status and other fields
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.stopTime": req.body.stopTime,
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// // Send immediate response to the client
// reply.code(200).send({ message: "Motor stopped successfully." });
// // Perform stop operations in the background
// (async () => {
// await delay(300000);
// // Update the existing motor data entry with stop details
// 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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
// const totalwaterpumped = quantityDelivered + water_pumped_till_now;
// await Tank.findOneAndUpdate(
// { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
// { $set: { total_water_added_from_midnight: totalwaterpumped } }
// );
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime: req.body.stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// })();
// // Return here to ensure the rest of the code is not executed for the stop action
// return;
// } else {
// // Update the motor stop status to "2" for start action
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
// );
// }
// // Check threshold settings if action is start
// if (action === "start") {
// if (req.body.threshold_type === "time") {
// // If threshold type is time, update threshold time
// // await Tank.updateOne(
// // { customerId, "connections.inputConnections.motor_id": motorId },
// // { $set: { "connections.inputConnections.$.manual_threshold_time": req.body.manual_threshold_time,startTime:req.body.startTime } }
// // );
// const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const newMotorData = new MotorData({
// customerId: customerId,
// motor_id: motorId,
// start_instance_id: start_instance_id,
// supplierTank: req.body.from,
// receiverTank: req.body.to,
// supplier_type: req.body.from_type,
// receiver_type: req.body.to_type,
// startTime: req.body.startTime,
// receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
// });
// await newMotorData.save();
// for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
// const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
// if (index !== -1) {
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime,[`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
// );
// }
// }
// // Start monitoring water level based on threshold time
// const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
// const intervalId = setInterval(async () => {
// const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
// //console.log(splr_tank_info3_waterlevel,"splr_tank_info3_waterlevel")
// const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
// // const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity, 10);
// // console.log(splr_tank_info3.capacity,splr_tank_info3_capacity,"splr_tank_info3_capacity")
// const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;
// // console.log(splr_tank_info3_percentage, "percentage for less than 20");
// if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
// console.log(splr_tank_info3_percentage,)
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// clearInterval(intervalId);
// await delay(300000);
// 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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
// const totalwaterpumped = quantityDelivered + water_pumped_till_now
// await Tank.findOneAndUpdate({customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase()}, { $set: { total_water_added_from_midnight: totalwaterpumped } })
// const stopTime = formatDate(new Date());
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime:stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// }
// }, 60000);
// } else if (req.body.threshold_type === "litres") {
// console.log("entered litres")
// const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const newMotorData = new MotorData({
// customerId: customerId,
// motor_id: motorId,
// start_instance_id: start_instance_id,
// supplierTank: req.body.from,
// receiverTank: req.body.to,
// supplier_type: req.body.from_type,
// receiver_type: req.body.to_type,
// startTime: req.body.startTime,
// receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
// });
// await newMotorData.save();
// // If threshold type is percentage, calculate percentage threshold
// const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// if (!receiver_tank_info) {
// throw new Error("Receiver tank not found.");
// }
// if (!supplier_tank_info) {
// throw new Error("Supplierr tank not found.");
// }
// const supplier_capacity = parseInt(supplier_tank_info.capacity, 10);
// const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10);
// const capacity = parseInt(receiver_tank_info.capacity, 10);
// const waterLevel = parseInt(receiver_tank_info.waterlevel, 10);
// const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);
// console.log(desired_percentage)
// const threshold_water_level = waterLevel+desired_percentage;
// const supplier_threshold = supplier_waterLevel-desired_percentage
// console.log(supplier_threshold,"supplier_threshold")
// for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
// const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
// if (index !== -1) {
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
// );
// }
// }
// // Update water level threshold
// // Start monitoring water level based on threshold percentage
// const intervalId = setInterval(async () => {
// // Check if water level has reached the threshold percentage
// const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
// if (current_water_level <= supplier_threshold) {
// // Stop the motor pump
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// clearInterval(intervalId); // Stop monitoring water level
// await delay(300000);
// 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 stopTime = formatDate(new Date());
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime:stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// }
// }, 20000); // Check water level every minute
// }
// }
// // Respond with success message
// reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
// } catch (err) {
// // Handle errors
// throw boom.boomify(err);
// }
// };
// exports.motorAction = async (req, reply) => {
// try {
// const customerId = req.params.customerId;
// const action = req.body.action;
// const motorId = req.body.motor_id;
// const start_instance_id = req.body.start_instance_id;
// //const fcmIds = req.body.fcmIds; // Assume this is provided in the request to notify users
// // Ensure motor_id is provided
// if (!motorId) {
// throw new Error("Motor ID is required.");
// }
// // Determine the motor stop status based on the action
// let motorStopStatus;
// if (action === "start") {
// motorStopStatus = "2"; // If action is start, set stop status to "2"
// } else if (action === "stop") {
// motorStopStatus = "1"; // If action is stop, set stop status to "1"
// } else {
// throw new Error("Invalid action provided.");
// }
// const users = await User.find({ customerId: customerId });
// const fcmIds = users.map(user => user.fcmId).filter(fcmId => fcmId);
// // Handle motor stop action
// if (action === "stop") {
// // Update the motor stop status and other fields
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.stopTime": req.body.stopTime,
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// // Send immediate response to the client
// reply.code(200).send({ message: "Motor stopped successfully." });
// // Send notification for motor stop
// for (const fcmId of fcmIds) {
// try {
// const response = await sendPushNotification(fcmId, 'Motor Stopped', `Motor has stopped at ${req.body.stopTime}.`);
// console.log('Notification sent successfully:', response);
// if (response.results[0].error === 'NotRegistered') {
// await User.updateOne({ fcmId: fcmId }, { $unset: { fcmId: "" } });
// console.log(`Removed unregistered FCM ID: ${fcmId}`);
// }
// } catch (error) {
// console.error('Error sending notification:', error);
// }
// }
// // Perform stop operations in the background
// (async () => {
// await delay(300000);
// // Update the existing motor data entry with stop details
// 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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
// const totalwaterpumped = quantityDelivered + water_pumped_till_now;
// await Tank.findOneAndUpdate(
// { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
// { $set: { total_water_added_from_midnight: totalwaterpumped } }
// );
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime: req.body.stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// })();
// // Return here to ensure the rest of the code is not executed for the stop action
// return;
// } else {
// // Update the motor stop status to "2" for start action
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
// );
// // Send notification for motor start
// for (const fcmId of fcmIds) {
// try {
// const response = await sendPushNotification(fcmId, 'Motor Started', `Motor has started at ${req.body.startTime}.`);
// console.log('Notification sent successfully:', response);
// if (response.results[0].error === 'NotRegistered') {
// await User.updateOne({ fcmId: fcmId }, { $unset: { fcmId: "" } });
// console.log(`Removed unregistered FCM ID: ${fcmId}`);
// }
// } catch (error) {
// console.error('Error sending notification:', error);
// }
// }
// }
// // Check threshold settings if action is start
// if (action === "start") {
// if (req.body.threshold_type === "time") {
// const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const newMotorData = new MotorData({
// customerId: customerId,
// motor_id: motorId,
// start_instance_id: start_instance_id,
// supplierTank: req.body.from,
// receiverTank: req.body.to,
// supplier_type: req.body.from_type,
// receiver_type: req.body.to_type,
// startTime: req.body.startTime,
// receiverInitialwaterlevel: parseInt(receiver_tank_info7.waterlevel, 10)
// });
// await newMotorData.save();
// for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
// const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
// if (index !== -1) {
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime, [`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
// );
// }
// }
// // Start monitoring water level based on threshold time
// const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
// const intervalId = setInterval(async () => {
// const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
// const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
// const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;
// if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
// // Send notification for low supplier tank percentage
// for (const fcmId of fcmIds) {
// try {
// const response = await sendPushNotification(fcmId, 'Low Water Level Alert', `Supplier tank water level is below 20% (${splr_tank_info3_percentage.toFixed(2)}%).`);
// console.log('Notification sent successfully:', response);
// if (response.results[0].error === 'NotRegistered') {
// await User.updateOne({ fcmId: fcmId }, { $unset: { fcmId: "" } });
// console.log(`Removed unregistered FCM ID: ${fcmId}`);
// }
// } catch (error) {
// console.error('Error sending notification:', error);
// }
// }
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// clearInterval(intervalId);
// await delay(300000);
// 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 water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
// const totalwaterpumped = quantityDelivered + water_pumped_till_now;
// await Tank.findOneAndUpdate(
// { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
// { $set: { total_water_added_from_midnight: totalwaterpumped } }
// );
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime: req.body.stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// }
// }, 60000); // Check every minute
// } else if (req.body.threshold_type === "litres") {
// console.log("entered litres")
// const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const newMotorData = new MotorData({
// customerId: customerId,
// motor_id: motorId,
// start_instance_id: start_instance_id,
// supplierTank: req.body.from,
// receiverTank: req.body.to,
// supplier_type: req.body.from_type,
// receiver_type: req.body.to_type,
// startTime: req.body.startTime,
// receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
// });
// await newMotorData.save();
// // If threshold type is percentage, calculate percentage threshold
// const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// if (!receiver_tank_info) {
// throw new Error("Receiver tank not found.");
// }
// if (!supplier_tank_info) {
// throw new Error("Supplierr tank not found.");
// }
// const supplier_capacity = parseInt(supplier_tank_info.capacity, 10);
// const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10);
// const capacity = parseInt(receiver_tank_info.capacity, 10);
// const waterLevel = parseInt(receiver_tank_info.waterlevel, 10);
// const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);
// console.log(desired_percentage)
// const threshold_water_level = waterLevel+desired_percentage;
// const supplier_threshold = supplier_waterLevel-desired_percentage
// console.log(supplier_threshold,"supplier_threshold")
// for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
// const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
// if (index !== -1) {
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
// );
// }
// }
// // Start monitoring water level based on threshold percentage
// const intervalId = setInterval(async () => {
// // Check if water level has reached the threshold percentage
// const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
// const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
// if (current_water_level <= supplier_threshold) {
// // Stop the motor pump
// await Tank.updateOne(
// { customerId, "connections.inputConnections.motor_id": motorId },
// {
// $set: {
// "connections.inputConnections.$.motor_stop_status": "1",
// "connections.inputConnections.$.threshold_type": null,
// "connections.inputConnections.$.manual_threshold_time": null,
// "connections.inputConnections.$.manual_threshold_percentage": null
// }
// }
// );
// clearInterval(intervalId); // Stop monitoring water level
// await delay(300000);
// 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 stopTime = formatDate(new Date());
// await MotorData.updateOne(
// { customerId, motor_id: motorId, start_instance_id: start_instance_id },
// {
// $set: {
// stopTime:stopTime,
// receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
// quantity_delivered: quantityDelivered.toString()
// }
// }
// );
// }
// }
// }, 20000);
// }
// }
// reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
// } catch (err) {
// // Handle errors
// throw boom.boomify(err);
// }
// };
const motorActionAuto = async (req, reply) => {
try {
const customerId = req.params.customerId;
const action = req.body.action;
const motorId = req.body.motor_id;
const motor_on_type = req.body.motor_on_type
const startTime = req.body.startTime;
const stopTime = req.body.stopTime;
const threshold = req.body.threshold || "unknown";
if (!motorId) {
throw new Error("Motor ID is required.");
}
let motorStopStatus;
const tank = await Tank.findOne({ customerId, "connections.inputConnections.motor_id": motorId });
const user = await User.findOne({ customerId });
const allowNotifications = user?.automaticStartAndStopNotify ?? true; // Default to true if not set
if (!tank) {
throw new Error("Tank not found for the provided motor ID.");
}
const { tankName, blockName, typeOfWater, fcmTokens } = tank; // Extracting necessary details
if (action === "start") {
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{
$set: {
"connections.inputConnections.$.motor_stop_status": "2",
"connections.inputConnections.$.startTime": req.body.startTime,
"connections.inputConnections.$.motor_on_type": "auto",
}
}
);
if (allowNotifications) {
eventEmitter.emit(
"motorStartAutomatic",
fcmTokens,
tankName,
blockName,
startTime,
"Automatic",
typeOfWater,
threshold
);
}
}
if (action === "stop") {
await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId },
{
$set: {
"connections.inputConnections.$.motor_stop_status": "1",
"connections.inputConnections.$.stopTime": req.body.stopTime,
"connections.inputConnections.$.motor_on_type": null,
}
}
);
const currentDateTime = new Date();
const formattedDate = currentDateTime.toLocaleDateString();
const formattedTime = currentDateTime.toLocaleTimeString();
if (allowNotifications) {
const stopMessage =
`🚰 Motor Name: ${tankName}-${blockName}-${typeOfWater}\n` +
`🛢️ Tank Name: '${tankName}'\n` +
`🏢 Block Name: '${blockName}'\n` +
`🕒 Pump stopped at: ${stopTime}\n` +
`⏳ Operation Duration: ${threshold} `;
// Send stop notification
await sendNotification(fcmTokens, "Arminta Water Management", stopMessage);
}
}
reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
} catch (err) {
console.error("Error in motorActionAuto:", err);
reply.code(500).send({ error: err.message });
}
};
const checkAutoMode = async () => {
try {
const tanks = await Tank.find();
for (const tank of tanks) {
for (const inputConnection of tank.connections.inputConnections) {
if (inputConnection.auto_mode === "active") {
console.log("This is automation for tank: " + tank.tankName);
const waterLevel = parseFloat(tank.waterlevel.replace(/,/g, ''));
const capacity = parseFloat(tank.capacity.replace(/,/g, ''));
const autoMinPercentage = parseFloat(tank.auto_min_percentage);
const autoMaxPercentage = parseFloat(tank.auto_max_percentage);
console.log(waterLevel,capacity,autoMinPercentage,autoMaxPercentage)
if (isNaN(waterLevel) || isNaN(capacity) || capacity === 0) {
console.error(`Invalid water level or capacity for tank: ${tank.tankName}`);
continue; // Skip this tank if the values are not valid
}
const currentPercentage = (waterLevel / capacity) * 100;
console.log("This is automation percentage: " + currentPercentage);
const now = moment().format('DD-MMM-YYYY - HH:mm');
console.log(now)
if (currentPercentage <= autoMinPercentage) {
await motorActionAuto({
params: { customerId: tank.customerId },
body: {
action: "start",
motor_id: inputConnection.motor_id,
motor_on_type: "auto",
startTime: now
}
}, {
code: (statusCode) => ({ send: (response) => console.log(response) })
});
} else if (currentPercentage >= autoMaxPercentage && inputConnection.motor_on_type === "auto") {
await motorActionAuto({
params: { customerId: tank.customerId },
body: {
action: "stop",
motor_id: inputConnection.motor_id,
motor_on_type: "auto",
stopTime: now
}
}, {
code: (statusCode) => ({ send: (response) => console.log(response) })
});
}
}
}
}
} catch (err) {
console.error("Error checking auto mode:", err);
}
};
// Set the interval to check every 15 seconds (15000 milliseconds)
setInterval(checkAutoMode, 15000);
// exports.calculateCapacity = async (req, reply) => {
// try {
// const shape = req.body.shape
// if(shape==="rectangle"){
// const { length, width, height } = req.body
// // Ensure all parameters are valid numbers
// if (isNaN(length) || isNaN(width) || isNaN(height)) {
// reply.code(400).send('Invalid input parameters')
// return
// }
// // Calculate the capacity of the water tank in liters
// const capacity = length * width * height * 1000
// reply.send({ status_code: 200, capacity: capacity});
// return { message: 'success' };
// }
// if(shape==="cylinder"){
// console.log("hii1")
// const { length,diameter } = req.body
// // Ensure all parameters are valid numbers
// if (isNaN(length) || isNaN(diameter)) {
// reply.code(400).send('Invalid input parameters')
// return
// }
// // Calculate the capacity of the water tank in liters
// const radius = diameter / 2
// const volume = Math.PI * Math.pow(radius, 2) * length
// const capacity = volume * 1000
// reply.send({ status_code: 200, capacity: capacity});
// return { message: 'success' };
// }
// // if(shape==="oval"){
// // console.log("hii3")
// // const { length, width, height } = req.body
// // // Ensure all parameters are valid numbers
// // if (isNaN(length) || isNaN(width) || isNaN(height)) {
// // reply.code(400).send('Invalid input parameters')
// // return
// // }
// // // Calculate the capacity of the water tank in liters
// // const radius = height / 2
// // const a = width - height
// // const area = Math.PI * radius * radius + 2 * radius * a
// // const volume = area * length
// // const capacity = volume * 1000
// // // Format the result with two decimal places and comma-separated thousands
// // const formattedCapacity = capacity.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
// // reply.send({ status_code: 200, capacity: formattedCapacity});
// // return { message: 'success' };
// // }
// // if(shape==="horizontalellipse"){
// // const { length, width, height } = req.body
// // // Ensure all parameters are valid numbers
// // if (isNaN(length) || isNaN(width) || isNaN(height)) {
// // reply.code(400).send('Invalid input parameters')
// // return
// // }
// // // Calculate the capacity of the water tank in liters
// // const radius1 = length / 2
// // const radius2 = width / 2
// // const volume = Math.PI * radius1 * radius2 * height
// // const capacity = volume * 1000
// // reply.send({ status_code: 200, capacity: capacity});
// // return { message: 'success' };
// // }
// if(shape==="userdefined"){
// const capacity = req.body
// reply.send({ status_code: 200, capacity: capacity});
// return { message: 'success' };
// }
// }
// catch (err) {
// throw boom.boomify(err);
// }
// };
// exports.calculateCapacity = async (req, reply) => {
// try {
// const shape = req.body.shape;
// if (shape === "rectangle") {
// const { length, width, height } = req.body;
// // Convert input units from feet to meters
// const length_m = length * 0.3048;
// const width_m = width * 0.3048;
// const height_m = height * 0.3048;
// console.log(length_m,width_m,height_m)
// // Ensure all parameters are valid numbers
// if (isNaN(length_m) || isNaN(width_m) || isNaN(height_m)) {
// reply.code(400).send("Invalid input parameters");
// return;
// }
// // Calculate the capacity of the water tank in liters
// const capacity = length_m * width_m * height_m * 1000;
// reply.send({ status_code: 200, capacity: capacity });
// return { message: "success" };
// }
// if (shape === "cylinder") {
// console.log("hii1");
// const { length, diameter } = req.body;
// // Convert input units from feet to meters
// const length_m = length * 0.3048;
// const diameter_m = diameter * 0.3048;
// // Ensure all parameters are valid numbers
// if (isNaN(length_m) || isNaN(diameter_m)) {
// reply.code(400).send("Invalid input parameters");
// return;
// }
// // Calculate the capacity of the water tank in liters
// const radius = diameter_m / 2;
// const volume = Math.PI * Math.pow(radius, 2) * length_m;
// const capacity = volume * 1000;
// reply.send({ status_code: 200, capacity: capacity });
// return { message: "success" };
// }
// // Add similar conversions for other shapes if necessary
// if (shape === "userdefined") {
// const capacity = req.body;
// reply.send({ status_code: 200, capacity: capacity });
// return { message: "success" };
// }
// } catch (err) {
// throw boom.boomify(err);
// }
// };
exports.calculateCapacity = async (req, reply) => {
try {
const shape = req.body.shape;
if (shape === "rectangle") {
const { length, width, height } = req.body;
// Convert input units from feet to meters
const length_m = length * 0.3048;
const width_m = width * 0.3048;
const height_m = height * 0.3048;
// Ensure all parameters are valid numbers
if (isNaN(length_m) || isNaN(width_m) || isNaN(height_m)) {
reply.code(400).send("Invalid input parameters");
return;
}
// Calculate the capacity of the water tank in liters
const capacity = length_m * width_m * height_m * 1000;
// Calculate the water capacity for a 1 centimeter height
const waterCapacityPerCm = length_m * width_m * 0.01 * 1000;
reply.send({ status_code: 200, capacity: capacity, waterCapacityPerCm: waterCapacityPerCm });
return { message: "success" };
}
if (shape === "cylinder") {
const { length, diameter } = req.body;
// Convert input units from feet to meters
const length_m = length * 0.3048;
const diameter_m = diameter * 0.3048;
// Ensure all parameters are valid numbers
if (isNaN(length_m) || isNaN(diameter_m)) {
reply.code(400).send("Invalid input parameters");
return;
}
// Calculate the capacity of the water tank in liters
const radius = diameter_m / 2;
const volume = Math.PI * Math.pow(radius, 2) * length_m;
const capacity = volume * 1000;
// Calculate the water capacity for a 1 centimeter height
const waterCapacityPerCm = Math.PI * Math.pow(radius, 2) * 0.01 * 1000;
reply.send({ status_code: 200, capacity: capacity, waterCapacityPerCm: waterCapacityPerCm });
return { message: "success" };
}
// Add similar conversions for other shapes if necessary
if (shape === "userdefined") {
const capacity = req.body.capacity; // Assuming capacity is provided directly
// Calculate the water capacity for a 1 centimeter height
const waterCapacityPerCm = capacity / req.body.height; // Assuming height of the shape is provided
reply.send({ status_code: 200, capacity: capacity, waterCapacityPerCm: waterCapacityPerCm });
return { message: "success" };
}
} catch (err) {
throw boom.boomify(err);
}
};
// exports.IotDevice = async (req, reply) => {
// try {
// const { hardwareId, mode, tanks } = req.body;
// // create a new tank document with the current date and time
// const currentDate = new Date();
// const date = currentDate.toISOString(); // save the date as an ISO string
// const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
// // Create an array of tank documents
// const tankDocuments = tanks.map(tank => ({
// tankhardwareId: tank.tankhardwareId,
// tankHeight: tank.tankHeight,
// maxLevel: tank.maxLevel,
// minLevel: tank.minLevel,
// date: date,
// time: time
// }));
// // create a new IotData document with the provided data
// const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });
// // save the document to MongoDB
// await ottank.save();
// // delete previous records except the three latest ones
// const previousRecords = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 })
// .skip(3); // skip the three latest documents
// for (const record of previousRecords) {
// await record.remove();
// }
// // get the latest three documents sorted in descending order of date and time
// const latestOttanks = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 })
// .limit(3);
// // send the latest documents
// reply.code(200).send({ latestOttanks });
// } catch (err) {
// // send an error response
// reply.code(500).send({ error: err.message });
// }
// };
exports.IotDevice = async (req, reply) => {
try {
const { hardwareId, mode, tanks } = req.body;
// create a new tank document with the current date and time
const currentDate = new Date();
const date = currentDate.toISOString(); // save the date as an ISO string
const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
// Create an array of tank documents
const tankDocuments = tanks.map(tank => ({
tankhardwareId: tank.tankhardwareId,
tankHeight: tank.tankHeight,
maxLevel: tank.maxLevel,
minLevel: tank.minLevel,
date: date,
time: time
}));
// create a new IotData document with the provided data
const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });
// save the document to MongoDB
await ottank.save();
// Delete excess records (keep only the latest three records)
const recordsToKeep = 3;
const recordsToDelete = await IotData.find({ hardwareId })
.sort({ date: -1, time: -1 })
.skip(recordsToKeep);
for (const record of recordsToDelete) {
await record.remove();
}
// Update waterlevel in tanksSchema for each tank
for (const tank of tanks) {
const { tankhardwareId, tankHeight } = tank;
// Find the corresponding tank in tanksSchema
const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
if (!existingTank) {
continue; // Skip to the next tank if not found
}
const customerId = existingTank.customerId;
const tank_name = existingTank.tankName;
// Update the waterlevel using the tankHeight value
const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
const tank_height = parseInt(tank_height1.toFixed(0), 10); // Ensure it's an integer
const water_level_height = tank_height - tankHeight;
const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
const water_level = parseInt(water_level_height * waterCapacityPerCm, 10);
if (water_level >= 0) {
existingTank.waterlevel = water_level;
// Save the updated tank document
await existingTank.save();
// Update linked tanks
for (const outputConnection of existingTank.connections.outputConnections) {
const linkedTank = await Tank.findOne({ customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
if (linkedTank) {
for (const inputConnection of linkedTank.connections.inputConnections) {
if (inputConnection.inputConnections === tank_name) {
inputConnection.water_level = water_level;
await linkedTank.save();
}
}
}
}
}
}
// Send the latest three documents
const latestOttanks = await IotData.find({ hardwareId })
.sort({ date: -1, time: -1 });
reply.code(200).send({ latestOttanks });
} catch (err) {
// send an error response
reply.code(500).send({ error: err.message });
}
};
console.log("this is for testing push")
exports.IotDeviceforstandalonedevice = async (req, reply) => {
try {
console.log("entered post for iotstandalone")
const { hardwareId, Motor_status, tanks } = req.body;
// create a new tank document with the current date and time
const currentDate = new Date();
const date = currentDate.toISOString(); // save the date as an ISO string
const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
// Create an array of tank documents
const tankDocuments = tanks.map(tank => ({
tankhardwareId: tank.tankhardwareId,
tankHeight: tank.tankHeight,
date: date,
time: time
}));
// create a new IotData document with the provided data
const ottank = new IotData({ hardwareId, Motor_status, tanks: tankDocuments, date, time });
// save the document to MongoDB
await ottank.save();
// Delete excess records (keep only the latest three records)
const recordsToKeep = 3;
const recordsToDelete = await IotData.find({ hardwareId })
.sort({ date: -1, time: -1 })
.skip(recordsToKeep);
for (const record of recordsToDelete) {
await record.remove();
}
// Update waterlevel in tanksSchema for each tank
for (const tank of tanks) {
const { tankhardwareId, tankHeight } = tank;
// Find the corresponding tank in tanksSchema
const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
if (!existingTank) {
continue; // Skip to the next tank if not found
}
const customerId = existingTank.customerId;
const tank_name = existingTank.tankName;
// Update the waterlevel using the tankHeight value
const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
const tank_height = parseInt(tank_height1.toFixed(0), 10); // Ensure it's an integer
const water_level_height = tank_height - tankHeight;
const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
const water_level = parseInt(water_level_height * waterCapacityPerCm, 10);
if (water_level >= 0) {
existingTank.waterlevel = water_level;
// Save the updated tank document
await existingTank.save();
// Update linked tanks
for (const outputConnection of existingTank.connections.outputConnections) {
const linkedTank = await Tank.findOne({ customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
if (linkedTank) {
for (const inputConnection of linkedTank.connections.inputConnections) {
if (inputConnection.inputConnections === tank_name) {
inputConnection.water_level = water_level;
await linkedTank.save();
}
}
}
}
}
}
const status = req.body.Motor_status;
console.log(status,"status")
// Find the tank that contains the specified motor_id in its inputConnections
const tank = await Tank.findOne({ "connections.inputConnections.motor_id": hardwareId });
if (!tank) {
return reply.status(404).send({
status_code: 404,
message: 'Motor not found for the specified motor_id'
});
}
console.log(hardwareId,"hardwareId")
console.log(status,"status")
// Find the inputConnection with the specified motor_id
const inputConnection = tank.connections.inputConnections.find(conn => conn.motor_id === hardwareId);
if (inputConnection) {
// Update the motor_status of the inputConnection
inputConnection.motor_status = status;
console.log(inputConnection)
// Check if motor_stop_status is "1" and status is "2"
if (inputConnection.motor_stop_status === "1" && status === "2") {
console.log("got into forced manual")
console.log(inputConnection.motor_on_type,"before if motor on type")
// Check if motor_on_type is not already "forced_manual"
if (inputConnection.motor_on_type !== "forced_manual") {
inputConnection.motor_on_type = "forced_manual";
console.log("entered forced manual of if")
inputConnection.motor_stop_status = "2";
// Update startTime to the current time in the specified format
const currentTime = new Date();
const formattedTime = currentTime.toLocaleString('en-GB', {
day: '2-digit',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
hour12: false,
}).replace(',', '');
inputConnection.startTime = formattedTime;
}
}
// Check if motor_stop_status is "1" and status is "2"
if (inputConnection.motor_stop_status === "2" && status === "1") {
console.log("got into forced manual stop")
console.log(inputConnection.motor_on_type,"before if motor on type stop")
// Check if motor_on_type is not already "forced_manual"
if (inputConnection.motor_on_type = "forced_manual") {
inputConnection.motor_on_type = "manual";
console.log("entered forced manual of if of stop")
// Update startTime to the current time in the specified format
inputConnection.motor_stop_status = "1";
}
}
}
// Save the updated tank
await tank.save();
// Send the latest three documents
const latestOttanks = await IotData.find({ hardwareId })
.sort({ date: -1, time: -1 });
reply.code(200).send({ latestOttanks });
} catch (err) {
// send an error response
reply.code(500).send({ error: err.message });
}
};
// exports.IotDevice3 = async (req, reply) => {
// try {
// const { hardwareId, mode, tanks } = req.body;
// // create a new tank document with the current date and time
// const currentDate = new Date();
// const date = currentDate.toISOString(); // save the date as an ISO string
// const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
// // Create an array of tank documents
// const tankDocuments = tanks.map(tank => ({
// tankhardwareId: tank.tankhardwareId,
// tankHeight: tank.tankHeight,
// maxLevel: tank.maxLevel,
// minLevel: tank.minLevel,
// date: date,
// time: time
// }));
// // create a new IotData document with the provided data
// const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });
// // save the document to MongoDB
// await ottank.save();
// // Delete excess records (keep only the latest three records)
// const recordsToKeep = 3;
// const recordsToDelete = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 })
// .skip(recordsToKeep);
// for (const record of recordsToDelete) {
// await record.remove();
// }
// // Update waterlevel in tanksSchema for each tank
// for (const tank of tanks) {
// const { tankhardwareId, tankHeight } = tank;
// // Find the corresponding tank in tanksSchema
// const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
// if (existingTank) {
// // Update the waterlevel using the tankHeight value
// const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
// console.log(tank_height1, 25);
// // The value of tank_height1 is a number, not a string, so you cannot use replace on it.
// // If you want to format it with commas, you can create a function to add commas to a number.
// function numberWithCommas(x) {
// return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// }
// // Now you can use the function to format the tank_height1 value with commas.
// const formatted_tank_height1 = numberWithCommas(tank_height1);
// console.log(formatted_tank_height1, 25);
// const tank_height = parseInt(formatted_tank_height1.replace(/,/g, ''), 10);
// console.log(tank_height);
// // console.log(tank_height,1)
// const water_level_height = tank_height - tankHeight
// console.log(water_level_height,2)
// const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10)
// console.log(waterCapacityPerCm,3)
// const water_level = water_level_height * waterCapacityPerCm;
// console.log(water_level, 4);
// // Function to add commas to a number
// function numberWithCommas(x) {
// return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// }
// const formatted_water_level = numberWithCommas(water_level);
// console.log(formatted_water_level, 4);
// existingTank.waterlevel = parseInt(formatted_water_level.replace(/,/g, ''), 10);
// console.log(existingTank.waterlevel);
// // Save the updated tank document
// await existingTank.save();
// for (const outputConnection of existingTank.connections.outputConnections) {
// const linkedTank = await Tank.findOne({ customerId: customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
// if (linkedTank) {
// // linkedTank.waterlevel = existingTank.waterlevel;
// //await linkedTank.save();
// // Update water level of tanks linked through input connections of the linked tank
// for (const inputConnection of linkedTank.connections.inputConnections) {
// if (inputConnection.inputConnections === tank_name) {
// inputConnection.water_level = water_level.toString();
// await linkedTank.save();
// }
// }
// }
// }
// }
// }
// // Send the latest three documents
// const latestOttanks = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 });
// reply.code(200).send({ latestOttanks });
// } catch (err) {
// // send an error response
// reply.code(500).send({ error: err.message });
// }
// };
// exports.IotDevice1 = async (req, reply) => {
// try {
// const { hardwareId, mode, tanks } = req.body;
// // create a new tank document with the current date and time
// const currentDate = new Date();
// const date = currentDate.toISOString(); // save the date as an ISO string
// const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
// // Create an array of tank documents
// const tankDocuments = tanks.map(tank => ({
// tankhardwareId: tank.tankhardwareId,
// tankHeight: tank.tankHeight,
// maxLevel: tank.maxLevel,
// minLevel: tank.minLevel,
// date: date,
// time: time
// }));
// // create a new IotData document with the provided data
// const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });
// // save the document to MongoDB
// await ottank.save();
// // Delete excess records (keep only the latest three records)
// const recordsToKeep = 3;
// const recordsToDelete = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 })
// .skip(recordsToKeep);
// for (const record of recordsToDelete) {
// await record.remove();
// }
// console.log(tanks)
// // Update waterlevel in tanksSchema for each tank
// for (const tank of tanks) {
// console.log(tank)
// const { tankhardwareId, tankHeight } = tank;
// console.log(hardwareId,tankhardwareId)
// // Find the corresponding tank in tanksSchema
// const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
// if (!existingTank) {
// console.log(`No tank found for tankhardwareId '${tankhardwareId}'. Skipping.`);
// continue; // Skip to the next iteration
// }
// console.log(existingTank,"existing tank")
// if (existingTank) {
// // Update the waterlevel using the tankHeight value
// const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
// console.log(tank_height1, 25);
// // The value of tank_height1 is a number, not a string, so you cannot use replace on it.
// // If you want to format it with commas, you can create a function to add commas to a number.
// function numberWithCommas(x) {
// return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// }
// // Now you can use the function to format the tank_height1 value with commas.
// const formatted_tank_height1 = numberWithCommas(tank_height1);
// console.log(formatted_tank_height1, 25);
// const tank_height = parseInt(formatted_tank_height1.replace(/,/g, ''), 10);
// console.log(tank_height);
// // console.log(tank_height,1)
// const water_level_height = tank_height - tankHeight
// console.log(water_level_height,2)
// const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10)
// console.log(waterCapacityPerCm,3)
// const water_level = water_level_height * waterCapacityPerCm;
// console.log(water_level, 4);
// // Function to add commas to a number
// function numberWithCommas(x) {
// return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// }
// const formatted_water_level = numberWithCommas(water_level);
// console.log(formatted_water_level, 4);
// existingTank.waterlevel = parseInt(formatted_water_level.replace(/,/g, ''), 10);
// console.log(existingTank.waterlevel);
// // Save the updated tank document
// await existingTank.save();
// for (const outputConnection of existingTank.connections.outputConnections) {
// const linkedTank = await Tank.findOne({ customerId: customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
// if (linkedTank) {
// // linkedTank.waterlevel = existingTank.waterlevel;
// //await linkedTank.save();
// // Update water level of tanks linked through input connections of the linked tank
// for (const inputConnection of linkedTank.connections.inputConnections) {
// if (inputConnection.inputConnections === tank_name) {
// inputConnection.water_level = water_level.toString();
// await linkedTank.save();
// }
// }
// }
// }
// }
// }
// // Send the latest three documents
// const latestOttanks = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 });
// reply.code(200).send({ latestOttanks });
// } catch (err) {
// // send an error response
// reply.code(500).send({ error: err.message });
// }
// };
// exports.IotDevice1 = async (req, reply) => {
// try {
// const { hardwareId, mode, tanks } = req.body;
// // create a new tank document with the current date and time
// const currentDate = new Date();
// const date = currentDate.toISOString(); // save the date as an ISO string
// const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
// // Create an array of tank documents
// const tankDocuments = tanks.map(tank => ({
// tankhardwareId: tank.tankhardwareId,
// tankHeight: tank.tankHeight,
// maxLevel: tank.maxLevel,
// minLevel: tank.minLevel,
// date: date,
// time: time
// }));
// // create a new IotData document with the provided data
// const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });
// // save the document to MongoDB
// await ottank.save();
// // Delete excess records (keep only the latest three records)
// const recordsToKeep = 3;
// const recordsToDelete = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 })
// .skip(recordsToKeep);
// for (const record of recordsToDelete) {
// await record.remove();
// }
// // Update waterlevel in tanksSchema for each tank
// for (const tank of tanks) {
// const { tankhardwareId, tankHeight } = tank;
// if (tankHeight === null || tankHeight === undefined) {
// continue; // Skip this iteration and move to the next tank
// }
// // Find the corresponding tank in tanksSchema
// const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
// if (existingTank) {
// // Update the waterlevel using the tankHeight value
// const tank_height = parseInt(existingTank.height.replace(/,/g, ''), 10) * 30.48;
// const water_level_height = tank_height - tankHeight;
// const customerId = existingTank.customerId;
// const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
// let water_level = water_level_height * waterCapacityPerCm;
// water_level = Math.round(water_level); // Round to nearest whole number
// existingTank.waterlevel = water_level.toString(); // Convert to string as per schema definition
// const tank_name = existingTank.tankName;
// // Save the updated tank document
// await existingTank.save();
// // Update water level of tanks linked through output connections
// for (const outputConnection of existingTank.connections.outputConnections) {
// const linkedTank = await Tank.findOne({ customerId: customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
// if (linkedTank) {
// // linkedTank.waterlevel = existingTank.waterlevel;
// //await linkedTank.save();
// // Update water level of tanks linked through input connections of the linked tank
// for (const inputConnection of linkedTank.connections.inputConnections) {
// if (inputConnection.inputConnections === tank_name) {
// inputConnection.water_level = water_level.toString();
// await linkedTank.save();
// }
// }
// }
// }
// }
// }
// // Send the latest three documents
// const latestOttanks = await IotData.find({ hardwareId })
// .sort({ date: -1, time: -1 });
// reply.code(200).send({ latestOttanks });
// } catch (err) {
// // send an error response
// reply.code(500).send({ error: err.message });
// }
// };
// exports.getIotD = async(req, reply) => {
// try {
// await IotData.find({hardwareId: req.query.hardwareId})
// .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.getIotD = async (req, reply) => {
try {
const latestRecords = await IotData.find({ hardwareId: req.query.hardwareId })
.sort({ date: -1, time: -1 }) // Sort by date and time in descending order
.limit(3) // Limit the result to 3 records
.exec();
reply.send({ status_code: 200, data: latestRecords, count: latestRecords.length });
} catch (err) {
console.error(err);
throw boom.boomify(err);
}
};
exports.getLatestData = async (req, reply) => {
try {
const hardwareId = req.params.hardwareId;
// get the latest two tank documents for the current hardwareId sorted in descending order of date and time
const latestTanks = await IotData.find({ hardwareId }).sort({ date: -1, time: -1 }).limit(2);
// if the number of documents for the current hardwareId is less than two, return an error response
if (latestTanks.length < 2) {
return reply.code(404).send({ error: 'Not enough data' });
}
// calculate the time difference between the latest and previous documents
const latestDate = new Date(latestTanks[0].date);
const previousDate = new Date(latestTanks[1].date);
const latestTime = latestTanks[0].time.split('.')[0]; // remove milliseconds
const previousTime = latestTanks[1].time.split('.')[0]; // remove milliseconds
latestDate.setHours(parseInt(latestTime.substring(0, 2)), parseInt(latestTime.substring(3, 5)), parseInt(latestTime.substring(6, 8)));
previousDate.setHours(parseInt(previousTime.substring(0, 2)), parseInt(previousTime.substring(3, 5)), parseInt(previousTime.substring(6, 8)));
const timeDiff = (latestDate.getTime() - previousDate.getTime()) / 1000; // convert from milliseconds to seconds
console.log(latestDate,previousDate,latestTime,previousTime,timeDiff)
reply.code(200).send({ timeDiff });
} catch (err) {
// send an error response
reply.code(500).send({ error: err.message });
}
};
exports.changesurveystatus = async (req, reply) => {
try {
const customerId = req.params.customerId;
const result = await User.findOneAndUpdate(
{ customerId: customerId },
{ $set: { survey_status: req.body.survey_status } },
{ new: true }
);
reply.code(200).send({ result });
} catch (err) {
// send an error response
reply.code(500).send({ error: err.message });
}
};
exports.checkStatusofIot = async (req, reply) => {
try {
// get a list of unique hardware IDs in the collection
const hardwareIds = await IotData.distinct('hardwareId');
// create an empty object to store the time differences for each hardware ID
const timeDiffs = {};
// loop over each hardware ID and calculate the time difference between the latest two records
for (const hardwareId of hardwareIds) {
// get the latest two records for the current hardware ID
const latestTanks = await IotData.find({ hardwareId }).sort({ date: -1, time: -1 }).limit(2);
// if the number of records for the current hardware ID is less than two, skip to the next ID
if (latestTanks.length < 2) {
continue;
}
// calculate the time difference between the latest and previous records for the current hardware ID
const latestDate = new Date(latestTanks[0].date);
const previousDate = new Date(latestTanks[1].date);
const latestTime = latestTanks[0].time.split('.')[0]; // remove milliseconds
const previousTime = latestTanks[1].time.split('.')[0]; // remove milliseconds
latestDate.setHours(parseInt(latestTime.substring(0, 2)), parseInt(latestTime.substring(3, 5)), parseInt(latestTime.substring(6, 8)));
previousDate.setHours(parseInt(previousTime.substring(0, 2)), parseInt(previousTime.substring(3, 5)), parseInt(previousTime.substring(6, 8)));
const timeDiff = (latestDate.getTime() - previousDate.getTime()) / 1000; // convert from milliseconds to seconds
// store the time difference for the current hardware ID
timeDiffs[hardwareId] = timeDiff;
}
// send the time differences for all hardware IDs
reply.code(200).send({ timeDiffs });
} catch (err) {
// send an error response
reply.code(500).send({ error: err.message });
}
};
exports.totalwaterLevelSum = async (request, reply) => {
const { tankLocation, typeOfWater } = request.query;
const waterlevelSum = await Tank.aggregate([
{
$match: { tankLocation, typeOfWater }
},
{
$group: {
_id: null,
totalWaterlevel: { $sum: { $toInt: '$waterlevel' } }
}
}
]);
const result = waterlevelSum[0]?totalWaterlevel : 0;
reply.send({ waterlevelSum: result });
}
exports.startUpdateLoop = async (request, reply) => {
const updateInterval = 5000;
setInterval(async () => {
try {
const iotTank = await IotData.findOne({ hardwareId: request.body.hardwareId });
if (!iotTank) {
console.log(`IOTtank not found for hardwareId ${request.body.hardwareId}`);
return;
}
const currentWaterlevel = Number(iotTank.tankHeight) * 200;
const tank = await Tank.findOne({ hardwareId: iotTank.hardwareId });
let combinedWaterlevel;
if (tank) {
combinedWaterlevel = currentWaterlevel + Number(tank.waterlevel);
} else {
combinedWaterlevel = currentWaterlevel;
}
await Tank.updateOne({ hardwareId: iotTank.hardwareId }, { $set: { waterlevel: combinedWaterlevel } });
console.log(`Waterlevel updated successfully for hardwareId ${iotTank.hardwareId}`);
console.log(`Previous waterlevel: ${tank ? tank.waterlevel : 0}`);
console.log(`Current waterlevel: ${currentWaterlevel}`);
console.log(`Combined waterlevel: ${combinedWaterlevel}`);
} catch (err) {
console.error(err);
}
}, updateInterval);
};
const updatewaterlevelsatmidnight = async () => {
console.log('Cron job triggered at:', moment().tz('Asia/Kolkata').format());
try {
const tanks = await Tank.find({});
for (const tank of tanks) {
tank.waterlevel_at_midnight = tank.waterlevel;
tank.total_water_added_from_midnight = "0";
await tank.save();
console.log(`Updated tank ${tank._id} waterlevel_at_midnight to ${tank.waterlevel}`);
}
console.log('Waterlevel noted in waterlevel_at_midnight');
} catch (error) {
console.error('Error occurred:', error);
}
};
// Schedule the task to run every day at 13:49 IST (1:49 PM IST)
cron.schedule('0 0 * * *', updatewaterlevelsatmidnight, {
timezone: "Asia/Kolkata"
});
let consumptionTask;
// Function to clear the specific scheduled task
const clearConsumptionSchedule = () => {
if (consumptionTask) {
consumptionTask.stop(); // Stop the existing task if it exists
consumptionTask = null; // Clear the reference
}
};
// Function to update total consumption till midnight
const updatetotalConsumptiontillmidnight = async () => {
console.log('Cron job triggered at:', moment().tz('Asia/Kolkata').format());
try {
const tanks = await Tank.find({});
for (const tank of tanks) {
const waterlevel_at_midnight = parseInt((tank.waterlevel_at_midnight).replace(/,/g, ''), 10);
const total_water_added_from_midnight = parseInt((tank.total_water_added_from_midnight).replace(/,/g, ''), 10);
const waterlevel = parseInt((tank.waterlevel).replace(/,/g, ''), 10);
const capacity = parseInt((tank.capacity).replace(/,/g, ''), 10);
console.log(waterlevel_at_midnight,total_water_added_from_midnight,waterlevel)
const totalconsumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel;
// const available_capacity = total_water_added_from_midnight + waterlevel;
const consumed_percentage = ((totalconsumption / capacity) * 100).toFixed(2);
console.log(totalconsumption,tank.tankName)
// Format the date in the desired format
const formattedDate = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
// Check if the record already exists
const existingRecord = await TankConsumptionOriginalSchema.findOne({
customerId: tank.customerId,
tankName: tank.tankName,
tankLocation: tank.tankLocation,
time: formattedDate
});
if (!existingRecord) {
// Create and save the new document if it doesn't exist
const newTankConsumption = new TankConsumptionOriginalSchema({
customerId: tank.customerId,
tankName: tank.tankName,
tankLocation: tank.tankLocation,
available_capacity: (tank.capacity).toString(),
consumption: totalconsumption.toString(),
consumed_percentage: consumed_percentage.toString(),
time: formattedDate, // Save the formatted date
block:tank.blockName,
typeofwater:tank.typeOfWater
});
await newTankConsumption.save();
console.log(`Created new record for tank ${tank.tankName} at ${formattedDate}`);
} else {
console.log(`Record already exists for tank ${tank.tankName} at ${formattedDate}`);
}
}
console.log('Waterlevel noted in waterlevel_at_midnight');
} catch (error) {
console.error('Error occurred:', error);
}
};
// Clear the existing schedule for this task before creating a new one
clearConsumptionSchedule();
// Schedule the task to run every day at 12:49 PM IST and store the reference
consumptionTask = cron.schedule('50 23 * * *', updatetotalConsumptiontillmidnight, {
timezone: "Asia/Kolkata"
});
console.log('Scheduled task to update total consumption till midnight.');
exports.deletemotordatarecordsbefore7days = async (req, reply) => {
try {
// Schedule the task to run every day at 10 seconds past the minute
cron.schedule('0 0 * * *', async () => {
try {
// Run the deletion task once a day
setInterval(async () => {
await deleteOldRecords();
}, 24 * 60 * 60 * 1000); // 24 hours in milliseconds
} catch (error) {
console.error('Error occurred:', error);
}
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.motorstatus = async (req, reply) => {
try {
const motor_id = req.params.motor_id;
console.log(motor_id)
const motorInfo = await Tank.findOne({ motor_id: motor_id });
console.log(motorInfo)
//return update;
reply.send({ status_code: 200,status:motorInfo.motor_status});
}
catch (err) {
throw boom.boomify(err);
}
};
exports.readMotorStatus = async (req, reply) => {
try {
const motor_id = req.query.motor_id;
console.log("entered read api for iot")
// Perform any necessary logic based on action (1: Start, 2: Stop)
// For example, you can update a database or trigger an action
const tanks = await Tank.find({});
let motor_stop_status = null;
for (let tank of tanks) {
const inputConnections = tank.connections.inputConnections;
const motorConnection = inputConnections.find(conn => conn.motor_id === motor_id);
if (motorConnection) {
// Check if motor_on_type is "forced_manual" and motor_stop_status is "1"
if (motorConnection.motor_on_type === "forced_manual" && motorConnection.motor_stop_status === "1") {
motor_stop_status = "2"; // Send motor_stop_status as "2"
} else {
motor_stop_status = motorConnection.motor_stop_status; // Otherwise, assign its original value
}
break;
}
}
if (!motor_stop_status) {
return reply.status(404).send({
status_code: 404,
message: 'Motor not found for the specified motor_id'
});
}
reply.send({
status_code: 200,
motor_stop_status: motor_stop_status
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.readMotorStatusFromIot = async (req, reply) => {
try {
const motor_id = req.query.motor_id;
console.log(motor_id)
// Find the tank that contains the specified motor_id in its inputConnections
const tank = await Tank.findOne({ "connections.inputConnections.motor_id": motor_id });
if (!tank) {
return reply.status(404).send({
status_code: 404,
message: 'Motor not found for the specified motor_id'
});
}
// Find the inputConnection with the specified motor_id
const inputConnection = tank.connections.inputConnections.find(conn => conn.motor_id === motor_id);
// Extract motor_status and motor_stop_status from the inputConnection
const motor_status = inputConnection.motor_status;
const motor_stop_status = inputConnection.motor_stop_status;
// Send the response with motor_status and motor_stop_status
reply.send({
status_code: 200,
motor_status: motor_status,
motor_stop_status: motor_stop_status
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.writeMotorStatus = async (req, reply) => {
try {
const motor_id = req.body.motor_id;
const status = req.body.status;
// Find the tank that contains the specified motor_id in its inputConnections
const tank = await Tank.findOne({ "connections.inputConnections.motor_id": motor_id });
if (!tank) {
return reply.status(404).send({
status_code: 404,
message: 'Motor not found for the specified motor_id'
});
}
// Find the inputConnection with the specified motor_id
const inputConnection = tank.connections.inputConnections.find(conn => conn.motor_id === motor_id);
// Update the motor_status of the inputConnection
inputConnection.motor_status = status;
// Save the updated tank
await tank.save();
// Send the response with the updated motor_status
reply.send({
status_code: 200,
motor_status: status
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.changeMotorStatus = async (req, reply) => {
try {
const motor_id = req.body.motor_id;
const action = req.body.action;
// Perform any necessary logic to handle motor status update from the device
// For example, update a database with the new status, current, and temp values
await Tank.updateOne(
{ "connections.inputConnections.motor_id": motor_id },
{
$set: {
"connections.inputConnections.$.motor_stop_status":action ,
}
}
);
// Send immediat
// Fetch the motor_status for the given motor_id
// Send the response with motor_stop_status and motor_status
reply.send({
status_code: 200,
motor_stop_status: action,
// motor_status: updatedMotor.motor_status // Assuming motor_status is a field in your Tank model
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.motortemperature = async (req, reply) => {
try {
const motor_id = req.params.motor_id;
console.log(motor_id)
const motorInfo = await Tank.findOne({ motor_id: motor_id });
console.log(motorInfo)
//return update;
reply.send({ status_code: 200,temperature:motorInfo.motor_temperfature});
}
catch (err) {
throw boom.boomify(err);
}
};
exports.update_auto_mode = async (req, reply) => {
try {
const customerId = req.params.customerId;
const { motor_id, auto_mode } = req.body;
// Update inputConnections' auto_mode
await Tank.updateOne(
{ customerId: customerId, "connections.inputConnections.motor_id": motor_id },
{ $set: { "connections.inputConnections.$.auto_mode": auto_mode } }
);
reply.send({ status_code: 200, message: "Auto mode and percentages updated successfully." });
} catch (error) {
throw boom.boomify(error);
}
};
exports.update_auto_percentage = async (req, reply) => {
try {
const customerId = req.params.customerId;
let { tankName, tankLocation, auto_min_percentage, auto_max_percentage, auto_mode_type } = req.body;
// Handle the optional parameters
tankName = tankName ? tankName : null;
tankLocation = tankLocation ? tankLocation.toLowerCase() : null;
const filter = { customerId };
// If tankName is not 'all', add it to the filter
if (tankName && tankName !== "all") {
filter.tankName = tankName;
}
// Only add tankLocation to the filter if tankName is not 'all'
if (tankLocation && tankName !== "all") {
filter.tankLocation = tankLocation;
}
console.log("Update filter:", JSON.stringify(filter, null, 2));
// Check if tanks exist
const matchingTanks = await Tank.find(filter);
console.log("Matching tanks:", matchingTanks);
if (matchingTanks.length === 0) {
return reply.send({ status_code: 400, message: "No matching records found." });
}
// Define the update fields
const updateData = {
auto_min_percentage: String(auto_min_percentage || "20"),
auto_max_percentage: String(auto_max_percentage || "80"),
auto_mode_type: auto_mode_type || "default",
};
let result;
if (tankName && tankName !== "all") {
// Update only one tank if tankName is specified and not "all"
result = await Tank.updateOne(filter, { $set: updateData });
} else {
// Update all tanks of the particular customer if tankName is "all"
result = await Tank.updateMany(filter, { $set: updateData });
// If auto_mode_type is default and tankName is "all", save or update the data in CustomerAutoPercentages
if (auto_mode_type === "default") {
const currentDate = new Date().toLocaleString("en-GB", { timeZone: "UTC" }); // Get current date in UTC
const formattedDate = currentDate.split(",").join(" -"); // Format it like '17-Dec-2024 - 15:56'
// Use findOneAndUpdate to either update the existing record or create a new one if it doesn't exist
const updateOrCreate = await CustomerAutoPercentages.findOneAndUpdate(
{ customerId }, // Search for the record with the customerId
{
$set: {
auto_min_percentage: String(auto_min_percentage || "20"),
auto_max_percentage: String(auto_max_percentage || "80"),
date: formattedDate,
},
},
{ upsert: true, new: true } // If no record found, create a new one; return the updated record
);
console.log("CustomerAutoPercentages updated/created:", updateOrCreate);
}
}
console.log("Update result:", result);
reply.send({ status_code: 200, message: "Auto mode and percentages updated successfully." });
} catch (error) {
console.error(error);
reply.send({ status_code: 500, message: "Internal server error." });
}
};
// Controller function to get CustomerAutoPercentages by customerId
exports.getCustomerAutoPercentages = async (req, reply) => {
try {
const { customerId } = req.params; // Extract customerId from the params
// Find the record in CustomerAutoPercentages based on customerId
const customerData = await CustomerAutoPercentages.findOne({ customerId });
if (!customerData) {
return reply.send({
status_code: 404,
message: "No data found for the provided customerId."
});
}
reply.send({
status_code: 200,
message: "Customer data retrieved successfully.",
data: customerData
});
} catch (error) {
console.error(error);
reply.send({
status_code: 500,
message: "Internal server error."
});
}
};
// exports.update_auto_percentage = async (req, reply) => {
// try {
// const customerId = req.params.customerId;
// let { tankName, tankLocation, auto_min_percentage, auto_max_percentage, auto_mode_type } = req.body;
// // Handle the optional parameters
// tankName = tankName ? tankName : null;
// tankLocation = tankLocation ? tankLocation.toLowerCase() : null;
// const filter = { customerId };
// // If tankName is not 'all', add it to the filter
// if (tankName && tankName !== "all") {
// filter.tankName = tankName;
// }
// // Only add tankLocation to the filter if tankName is not 'all'
// if (tankLocation && tankName !== "all") {
// filter.tankLocation = tankLocation;
// }
// console.log("Update filter:", JSON.stringify(filter, null, 2));
// // Check if tanks exist
// const matchingTanks = await Tank.find(filter);
// console.log("Matching tanks:", matchingTanks);
// if (matchingTanks.length === 0) {
// return reply.send({ status_code: 400, message: "No matching records found." });
// }
// // Define the update fields
// const updateData = {
// auto_min_percentage: String(auto_min_percentage || "20"),
// auto_max_percentage: String(auto_max_percentage || "80"),
// auto_mode_type: auto_mode_type || "default",
// };
// let result;
// if (tankName && tankName !== "all") {
// // Update only one tank if tankName is specified and not "all"
// result = await Tank.updateOne(filter, { $set: updateData });
// } else {
// // Update all tanks of the particular customer if tankName is "all"
// result = await Tank.updateMany(filter, { $set: updateData });
// }
// console.log("Update result:", result);
// reply.send({ status_code: 200, message: "Auto mode and percentages updated successfully." });
// } catch (error) {
// console.error(error);
// reply.send({ status_code: 500, message: "Internal server error." });
// }
// };
//storing water level for every 15 minutes
const getFormattedISTTime = () => {
return moment().tz('Asia/Kolkata').format('DD-MM-YYYY hh:mm:ss A');
};
const storeWaterLevels = async () => {
try {
const tanks = await Tank.find({});
const currentTime = getFormattedISTTime();
const waterLevelRecords = tanks.map(tank => ({
customerId: tank.customerId,
tankName: tank.tankName,
tankLocation: tank.tankLocation,
waterlevel: tank.waterlevel,
time: currentTime
}));
await TankWaterLevel.insertMany(waterLevelRecords);
console.log('Water levels stored successfully');
} catch (error) {
console.error('Error storing water levels:', error);
}
};
setInterval(storeWaterLevels, 15 * 60 * 1000);
console.log('Cron job scheduled to update water levels at midnight');
exports.getBlockData = async (req, reply) => {
try {
const customerId = req.params.customerId;
// Get all tank documents for the current customerId
const tanks = await Tank.find({ customerId });
// Extract the blockName from each tank
const blockNames = tanks.map(tank => tank.blockName);
// Remove duplicates by converting the array to a Set and then back to an array
const uniqueBlockNames = [...new Set(blockNames)];
// Add "all" and "nduku sneha antha kopam" to the block names
uniqueBlockNames.unshift("All");
// Send the unique blockNames in the response
reply.code(200).send({ blockNames: uniqueBlockNames });
} catch (err) {
// Log the error for debugging purposes
console.error(err);
// Send an error response
reply.code(500).send({ error: err.message });
}
};
// const mqtt = require('mqtt');
// // const moment = require('moment-timezone');
// // const IotData = require('./models/IotData'); // Replace with your actual model
// // const Tank = require('./models/Tank'); // Replace with your actual model
// // A map to keep track of MQTT clients by hw_Id
// const mqttClients = new Map();
// // Function to create a new MQTT client for a specific hw_Id
// function createMqttClient(hw_Id) {
// const client = mqtt.connect('mqtt://35.207.198.4:1883'); // Connect to the MQTT broker
// client.on('connect', () => {
// console.log(`Client for hw_Id ${hw_Id} connected to MQTT broker`);
// client.subscribe('water/iot-data', (err) => {
// if (err) {
// console.error(`Error subscribing to topic for hw_Id ${hw_Id}:`, err);
// } else {
// console.log(`Client for hw_Id ${hw_Id} subscribed to water/iot-data topic`);
// }
// });
// });
// client.on('message', async (topic, message) => {
// if (topic === 'water/iot-data') {
// try {
// const data = JSON.parse(message.toString());
// const { hw_Id: receivedHwId, Motor_status, tanks } = data.objects;
// // Ensure we process data only for the current client
// if (receivedHwId !== hw_Id) return;
// // Get the current date and time
// const currentDate = new Date();
// const date = currentDate.toISOString(); // ISO string for date
// const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' }); // Time in 'HH:MM:SS'
// // Create tank documents for the received tanks
// const tankDocuments = tanks.map(tank => ({
// tankhardwareId: tank.Id,
// tankHeight: tank.level,
// date,
// time
// }));
// // Save IoT data
// const iotTankData = new IotData({
// hardwareId: receivedHwId,
// Motor_status,
// tanks: tankDocuments,
// date,
// time
// });
// await iotTankData.save();
// // Delete excess records (keep only the latest three)
// const recordsToKeep = 3;
// const recordsToDelete = await IotData.find({ hardwareId: receivedHwId })
// .sort({ date: -1, time: -1 })
// .skip(recordsToKeep);
// for (const record of recordsToDelete) {
// await record.remove();
// }
// // Process tanks
// for (const tank of tanks) {
// const { Id: tankhardwareId, level: tankHeight } = tank;
// const existingTank = await Tank.findOne({ hardwareId: receivedHwId, tankhardwareId });
// if (!existingTank) continue;
// const customerId = existingTank.customerId;
// const tank_name = existingTank.tankName;
// const tankHeightInCm = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
// const tank_height = parseInt(tankHeightInCm.toFixed(0), 10);
// const waterLevelHeight = tank_height - tankHeight;
// const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
// const waterLevel = parseInt(waterLevelHeight * waterCapacityPerCm, 10);
// if (tankHeight > 0 && waterLevel >= 0) {
// existingTank.waterlevel = waterLevel;
// await existingTank.save();
// for (const outputConnection of existingTank.connections.outputConnections) {
// const linkedTank = await Tank.findOne({
// customerId,
// tankName: outputConnection.outputConnections,
// tankLocation: outputConnection.output_type
// });
// if (linkedTank) {
// for (const inputConnection of linkedTank.connections.inputConnections) {
// if (inputConnection.inputConnections === tank_name) {
// inputConnection.water_level = waterLevel;
// await linkedTank.save();
// }
// }
// }
// }
// }
// }
// // Update motor status
// const status = Motor_status;
// const motorTank = await Tank.findOne({ "connections.inputConnections.motor_id": receivedHwId });
// if (motorTank) {
// const inputConnection = motorTank.connections.inputConnections.find(conn => conn.motor_id === receivedHwId);
// if (inputConnection) {
// inputConnection.motor_status = status;
// if (inputConnection.motor_stop_status === "1" && status === 2 && inputConnection.motor_on_type !== "forced_manual") {
// const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
// inputConnection.motor_stop_status = "2";
// inputConnection.motor_on_type = "forced_manual";
// inputConnection.startTime = currentTime;
// }
// if (inputConnection.motor_stop_status === "2" && status === 1) {
// inputConnection.motor_stop_status = "1";
// }
// await motorTank.save();
// }
// }
// console.log(`Data processed successfully for hw_Id: ${receivedHwId}`);
// } catch (err) {
// console.error(`Error processing message for hw_Id ${hw_Id}:`, err.message);
// }
// }
// });
// return client;
// }
// // Handle incoming MQTT messages for water/iot-data topic
// const mainClient = mqtt.connect('mqtt://35.207.198.4:1883');
// mainClient.on('connect', () => {
// console.log('Main client connected to MQTT broker');
// mainClient.subscribe('water/iot-data', (err) => {
// if (err) {
// console.error('Error subscribing to water/iot-data topic:', err);
// }
// });
// });
// mainClient.on('message', (topic, message) => {
// if (topic === 'water/iot-data') {
// try {
// const data = JSON.parse(message.toString());
// const { hw_Id } = data.objects;
// if (!mqttClients.has(hw_Id)) {
// const client = createMqttClient(hw_Id);
// mqttClients.set(hw_Id, client);
// }
// } catch (err) {
// console.error('Error handling message in main client:', err.message);
// }
// }
// });
const mqtt = require('mqtt');
require('dotenv').config();
// **Persistent MQTT Connection**
const client = mqtt.connect('mqtt://35.207.198.4:1883', {
clientId: `mqtt_server_${Math.random().toString(16).substr(2, 8)}`,
clean: false, // Ensures MQTT retains subscriptions
reconnectPeriod: 2000, // Reconnect every 2 seconds
});
const subscribedTopics = new Set();
const activeDevices = new Set(); // Keep track of active devices
client.on('connect', () => {
console.log('✅ Connected to MQTT broker');
// **Ensure re-subscriptions after reconnect**
subscribedTopics.forEach(topic => {
client.subscribe(topic, { qos: 1 }, (err) => {
if (err) {
console.error(`❌ Error resubscribing to ${topic}:`, err);
} else {
console.log(`🔄 Resubscribed to ${topic}`);
}
});
});
// **Subscribe to new device announcements**
client.subscribe('water/iot-data/announce', { qos: 1 }, (err) => {
if (err) {
console.error('❌ Error subscribing to announcement topic:', err);
} else {
console.log('📡 Subscribed to water/iot-data/announce');
}
});
});
client.on('message', async (topic, message) => {
console.log(`📩 Message received on topic ${topic}: ${message.toString()}`);
try {
const data = JSON.parse(message.toString());
// **Handle device announcements**
if (topic === 'water/iot-data/announce') {
if (!data.objects || !data.objects.hw_Id) {
console.error("❌ Invalid announcement format. Missing hw_Id.");
return;
}
const hw_Id = data.objects.hw_Id;
const deviceTopic = `water/iot-data/${hw_Id}`;
if (!subscribedTopics.has(deviceTopic)) {
client.subscribe(deviceTopic, { qos: 1 }, (err) => {
if (err) {
console.error(`❌ Error subscribing to ${deviceTopic}:`, err);
} else {
console.log(`✅ Subscribed to ${deviceTopic}`);
subscribedTopics.add(deviceTopic);
activeDevices.add(hw_Id);
console.log('📡 Active Devices:', Array.from(activeDevices));
// ✅ **Now also process data**
processIotData(hw_Id, data);
}
});
} else {
console.log(`🔄 Already subscribed to ${deviceTopic}, processing data.`);
processIotData(hw_Id, data);
}
return;
}
// **Process IoT Data for device topics**
if (topic.startsWith('water/iot-data/')) {
setImmediate(() => {
console.log(`🚀 Entering processIotData() for topic: ${topic}`);
const hw_Id = topic.split('/')[2];
processIotData(hw_Id, data);
});
}
} catch (err) {
console.error('❌ Error processing message:', err.message);
}
});
client.on('error', (err) => console.error('❌ MQTT Error:', err));
client.on('close', () => console.log('⚠️ MQTT Connection Closed.'));
client.on('offline', () => console.log('⚠️ MQTT Broker Offline.'));
async function processIotData(hw_Id, data) {
try {
console.log(`📡 Processing IoT Data for hw_Id: ${hw_Id}`, JSON.stringify(data, null, 2));
if (!data.objects || !data.objects.tanks) {
console.error(`❌ Missing 'tanks' in data for hw_Id: ${hw_Id}`);
return;
}
const { Motor_status, tanks } = data.objects;
const currentDate = new Date();
const date = currentDate.toISOString(); // ISO string for date
const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });
const tankDocuments = tanks.map(tank => ({
tankhardwareId: tank.Id,
tankHeight: tank.level,
date,
time
}));
const iotTankData = new IotData({
hardwareId: hw_Id,
Motor_status,
tanks: tankDocuments,
date,
time
});
await iotTankData.save();
// Delete excess records (keep only the latest three records)
// const recordsToKeep = 3;
// const recordsToDelete = await IotData.find({ hardwareId: hw_Id })
// .sort({ date: -1, time: -1 })
// .skip(recordsToKeep);
// for (const record of recordsToDelete) {
// await record.remove();
// }
// Process each tank
for (const tank of tanks) {
const { Id: tankhardwareId, level: tankHeight } = tank;
const existingTank = await Tank.findOne({ hardwareId: hw_Id, tankhardwareId });
if (!existingTank) continue;
const customerId = existingTank.customerId;
const tank_name = existingTank.tankName;
const tankHeightInCm = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
const tank_height = parseInt(tankHeightInCm.toFixed(0), 10);
const waterLevelHeight = tank_height - tankHeight;
const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
const waterLevel = parseInt(waterLevelHeight * waterCapacityPerCm, 10);
console.log(`🚰 Tank [${tankhardwareId}] - Level: ${tankHeight}, Calculated Water Level: ${waterLevel}`);
if (tankHeight <= 0) {
const now = moment().tz('Asia/Kolkata');
const formattedNow = now.format('DD-MMM-YYYY - HH:mm:ss');
if (existingTank.slave_status !== "not_working") {
if (!existingTank.slave_disconnected_time) {
// First time signal is lost
existingTank.slave_status = "signal_lost";
existingTank.slave_disconnected_time = formattedNow;
await existingTank.save();
console.log(`⚠️ Slave signal lost for tank [${tankhardwareId}] at ${formattedNow}`);
} else if (existingTank.slave_status === "signal_lost") {
const disconnectedMoment = moment(existingTank.slave_disconnected_time, 'DD-MMM-YYYY - HH:mm:ss');
if (!disconnectedMoment.isValid()) {
console.error(`❌ Invalid slave_disconnected_time format for tank [${tankhardwareId}]`);
} else {
const minutesDiff = now.diff(disconnectedMoment, 'minutes');
console.log(`⏳ Minutes since disconnect for tank [${tankhardwareId}]: ${minutesDiff} min`);
if (minutesDiff >= 5) {
existingTank.slave_status = "not_working";
await existingTank.save();
console.log(`❌ Slave marked as not_working for tank [${tankhardwareId}] after ${minutesDiff} minutes`);
} else {
console.log(` Still within 5-minute window for tank [${tankhardwareId}], no update yet`);
}
}
}
} else {
console.log(`⏩ Slave already marked as not_working for tank [${tankhardwareId}], skipping update`);
}
}
if (tankHeight > 0 && waterLevel >= 0) {
existingTank.waterlevel = waterLevel;
existingTank.slave_status = "working";
existingTank.slave_disconnected_time = null;
await existingTank.save();
for (const outputConnection of existingTank.connections.outputConnections) {
const linkedTank = await Tank.findOne({ customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
if (linkedTank) {
for (const inputConnection of linkedTank.connections.inputConnections) {
if (inputConnection.inputConnections === tank_name) {
inputConnection.water_level = waterLevel;
await linkedTank.save();
}
}
}
}
}
}
// Update motor status
const status = Motor_status;
const motorTank = await Tank.findOne({ "connections.inputConnections.motor_id": hw_Id });
if (!motorTank) {
console.log('⚠️ Motor not found for specified motor_id');
return;
}
const inputConnection = motorTank.connections.inputConnections.find(conn => conn.motor_id === hw_Id);
if (inputConnection) {
inputConnection.motor_status = status;
const now1 = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm:ss');
const nowMoment = moment(now1, 'DD-MMM-YYYY - HH:mm:ss');
const startMoment = moment(inputConnection.startTime, 'DD-MMM-YYYY - HH:mm:ss');
const stopMoment = moment(inputConnection.stopTime, 'DD-MMM-YYYY - HH:mm:ss');
if (inputConnection.motor_stop_status === "1" && status === 2 && nowMoment.diff(stopMoment, 'seconds') >= 15 && inputConnection.motor_on_type !== "forced_manual") {
const currentTime = moment().tz('Asia/Kolkata');
const formattedTime = currentTime.format('DD-MMM-YYYY - HH:mm');
const startTime1 = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm:ss');
const startInstanceId = `${hw_Id}${formattedTime}`;
inputConnection.motor_stop_status = "2";
inputConnection.motor_on_type = "forced_manual";
inputConnection.startTime = startTime1;
inputConnection.start_instance_id = startInstanceId;
const newMotorData = new MotorData({
customerId:motorTank.customerId,
motor_id: hw_Id,
start_instance_id: startInstanceId,
supplierTank: inputConnection.inputConnections,
receiverTank: motorTank.tankName,
supplier_type: inputConnection.input_type,
receiver_type: motorTank.tankLocation,
startTime: formattedTime,
receiverInitialwaterlevel: parseInt(motorTank.waterlevel, 10),
started_by:"manual"
});
await newMotorData.save();
}
if (inputConnection.motor_stop_status === "2" && status === 1 && nowMoment.diff(startMoment, 'seconds') >= 15) {
const motorData = await MotorData.findOne({ customerId:motorTank.customerId, motor_id: hw_Id, start_instance_id: inputConnection.start_instance_id });
const startinstance = inputConnection.start_instance_id;
const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
const stopTime1 = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm:ss');
inputConnection.motor_stop_status = "1";
inputConnection.motor_on_type = "manual";
inputConnection.stopTime = stopTime1;
inputConnection.start_instance_id = null;
const motorId = hw_Id;
if (motorIntervals[motorId]) {
clearInterval(motorIntervals[motorId]);
delete motorIntervals[motorId];
console.log("motor interval deleted")
}
console.log(motorData,"motorData")
if (motorData) {
const receiverTank = await Tank.findOne({ customerId:motorTank.customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
const totalwaterpumped = quantityDelivered + water_pumped_till_now;
const start = moment(motorData.startTime, 'DD-MMM-YYYY - HH:mm');
const stop = moment(currentTime, 'DD-MMM-YYYY - HH:mm');
const duration = moment.duration(stop.diff(start));
const runtime = Math.floor(duration.asMinutes()); // runtime in minutes
await Tank.findOneAndUpdate(
{ customerId:motorTank.customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
{ $set: { total_water_added_from_midnight: totalwaterpumped } }
);
await MotorData.updateOne(
{ customerId:motorTank.customerId, motor_id: motorId, start_instance_id: startinstance },
{
$set: {
stopTime: currentTime,
receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
quantity_delivered: quantityDelivered.toString(),
runtime: runtime.toString(),
stopped_by:"manual"
}
}
);
}
}
await motorTank.save();
}
console.log(`✅ Data processed successfully for hw_Id: ${hw_Id}`);
} catch (err) {
console.error('❌ Error processing IoT data:', err.message);
}
}
function logSets() {
console.log("Subscribed Topics:", Array.from(subscribedTopics));
console.log("Active Devices:", Array.from(activeDevices));
console.log("motorIntervals:", motorIntervals);
}
// Call logSets every 30 seconds
setInterval(logSets, 30000);
const sendMotorNotifications = async () => {
// console.log("🔄 Checking for motor notifications...");
// Find motors that need a start or stop notification
const motors = await Tank.find({
"connections.inputConnections.motor_id": { $exists: true },
});
for (const motorTank of motors) {
const inputConnection = motorTank.connections.inputConnections.find(
(conn) => conn.motor_id
);
const status = inputConnection.motor_status
//console.log("motorTank",inputConnection)
// console.log("inputConnection.motor_on_type ",inputConnection.motor_on_type )
if (!inputConnection) continue;
const { customerId, blockName, tankName } = motorTank;
const fcmTokens = await getFcmTokens(customerId); // Get FCM tokens for this customer
if (!fcmTokens.length) continue;
// 🔹 Motor Start Condition
if (
inputConnection.motor_stop_status === "2" && inputConnection.motor_on_type === "forced_manual" &&
!motorTank.motor_start_notified
) {
console.log("✅ Sending Motor Start Notification...");
eventEmitter.emit(
"sendMotorStartNotification",
inputConnection.motor_id,
customerId,
fcmTokens,
inputConnection.water_level || 0,
blockName,
tankName,
"forced_manual",
inputConnection.manual_threshold_time
);
// Mark notification as sent
motorTank.motor_start_notified = true;
motorTank.motor_stop_notified = false; // Reset stop notification flag
await motorTank.save();
}
// 🔹 Motor Stop Condition
if (
inputConnection.motor_stop_status === "1" &&
!motorTank.motor_stop_notified && inputConnection.motor_on_type === "forced_manual"
) {
console.log("✅ Sending Motor Stop Notification...");
eventEmitter.emit(
"sendMotorStopNotification",
inputConnection.motor_id,
customerId,
fcmTokens,
inputConnection.water_level || 0,
blockName,
tankName,
"forced_manual"
);
// Mark notification as sent
motorTank.motor_stop_notified = true;
motorTank.motor_start_notified = false; // Reset start notification flag
await motorTank.save();
}
}
};
const getFcmTokens = async (customerId) => {
const user = await User.findOne({ customerId }).select("fcmIds");
return user?.fcmIds?.filter((token) => token) || [];
};
//Run the notification check every second
cron.schedule("* * * * * *", async () => {
await sendMotorNotifications();
});
//
// API function to get survey data for a particular installer
//
exports.getPendingAndCompletedsurveyOfparticularInstaller = async (request, reply) => {
try {
const { installationId } = request.params;
const { survey_status } = request.body;
const surveyData = await User.find({ installationId, survey_status });
reply.send({
status_code: 200,
surveyData,
});
} catch (err) {
console.error('❌ Error fetching survey data:', err);
throw boom.boomify(err);
}
};
exports.getPendingAndCompletedsurveyOfparticularInstaller = async (request, reply) => {
try {
const { installationId } = request.params;
const survey_status = request.body;
const surveydata = await User.find({
installationId,
survey_status,
});
// Send the response, including both total consumption and filtered consumption records
reply.send({
status_code: 200,
surveydata,
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.consumptionofparticulartank = async (request, reply) => {
try {
const { customerId } = request.params;
const { startDate, stopDate, tankName, tankLocation, block } = request.body;
// Convert input dates into proper JavaScript Date objects for comparison
const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();
end.setHours(23, 59, 59, 999); // Ensure full day is included
// Find the tank by customerId, tankLocation, and tankName
const tank = await Tank.findOne({
customerId,
tankLocation: tankLocation || "overhead", // Default to "overhead" if not provided
tankName,
});
if (!tank) {
return reply.status(404).send({
status_code: 404,
message: "Tank not found",
});
}
const waterlevel_at_midnight = parseInt(tank.waterlevel_at_midnight.replace(/,/g, ""), 10);
const total_water_added_from_midnight = parseInt(tank.total_water_added_from_midnight.replace(/,/g, ""), 10);
const waterlevel = parseInt(tank.waterlevel.replace(/,/g, ""), 10);
// Fetch all records for the tank (no date filtering yet)
const tankConsumptions = await TankConsumptionOriginalSchema.find({
customerId,
tankName,
tankLocation: tankLocation,
});
// Filter records in JavaScript by comparing the 'time' field after converting to Date
const filteredConsumptions = tankConsumptions.filter((record) => {
const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").toDate();
return recordTime >= start && recordTime <= end;
});
// Sort filtered records by date (ascending)
filteredConsumptions.sort((a, b) => {
const dateA = moment(a.time, "DD-MMM-YYYY - HH:mm").toDate();
const dateB = moment(b.time, "DD-MMM-YYYY - HH:mm").toDate();
return dateA - dateB; // Sort in ascending order
});
// Calculate total consumption from filtered records
const total_consumption_from_records = filteredConsumptions.reduce((acc, record) => {
return acc + parseInt(record.consumption, 10);
}, 0);
// Calculate final consumption
const consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel + total_consumption_from_records;
// Prepare response data
const tankData = {
tankname: tank.tankName,
totalConsumption: consumption,
block: tank.blockName,
TypeofWater: tank.typeOfWater,
location: tank.tankLocation,
capacity: tank.capacity,
waterlevel: tank.waterlevel,
};
const stopDateMoment = moment(stopDate, "DD-MMM-YYYY - HH:mm");
const today = moment().startOf('day');
if (stopDateMoment.isSame(today, 'day')) {
const latestConsumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel;
const nowFormatted = moment().format("DD-MMM-YYYY - HH:mm");
filteredConsumptions.push({
tankName: tank.tankName,
consumption: latestConsumption.toString(),
time: nowFormatted
});
}
// Send the response, including both total consumption and filtered consumption records
reply.send({
status_code: 200,
tankData,
totalConsumption: consumption,
consumptionRecords: filteredConsumptions,
});
} catch (err) {
throw boom.boomify(err);
}
};
// // Set start and end dates
// const startDate = new Date("2024-08-20T00:00:00Z");
// const endDate = new Date("2024-11-04T00:00:00Z");
// // Tank names array with respective blocks
// const tanks = [
// { tankName: "REAL TANK OH", block: "A" },
// { tankName: "DUMMY TANK OH1", block: "BLOCK C" },
// { tankName: "DUMMY TANK OH2", block: "BLOCK D" },
// { tankName: "DUMMY TANK OH3", block: "BLOCK C" },
// { tankName: "DUMMY TANK OH4", block: "BLOCK C" },
// { tankName: "DUMMY TANK OH5", block: "BLOCK C" },
// { tankName: "DUMMY TANK OH6", block: "BLOCK C" }
// ];
// const customerId = "AWSUSKY4";
// const tankLocation = "overhead";
// const typeofwater = "Bore Water";
// // Function to format date to "DD-MMM-YYYY - HH:mm"
// function formatDateCustom(date) {
// const options = { day: '2-digit', month: 'short', year: 'numeric' };
// return date.toLocaleDateString('en-GB', options).replace(/ /g, '-') + " - 23:55";
// }
// // Main function to generate data
// async function generateData() {
// for (let date = new Date(startDate); date <= endDate; date.setDate(date.getDate() + 1)) {
// const formattedDate = formatDateCustom(date); // Format date to "DD-MMM-YYYY - 23:55"
// for (const { tankName, block } of tanks) {
// try {
// const existingRecord = await TankConsumptionOriginalSchema.findOne({
// customerId: customerId,
// tankName: tankName,
// tankLocation: tankLocation,
// time: formattedDate
// }).exec();
// console.log(`Checking record for ${tankName} on ${formattedDate}: ${existingRecord ? 'Exists' : 'Does not exist'}`);
// if (!existingRecord) {
// // Random consumption between 7000 and 8000
// const randomConsumption = Math.floor(Math.random() * (8000 - 7000 + 1)) + 7000;
// // Create a new document and save it
// const newRecord = new TankConsumptionOriginalSchema({
// customerId: customerId,
// tankName: tankName,
// tankLocation: tankLocation,
// consumption: randomConsumption.toString(),
// time: formattedDate,
// block: block,
// typeofwater: typeofwater,
// __v: 0
// });
// await newRecord.save(); // Use .save() method to insert the record
// console.log(`Inserted record for ${tankName} on ${formattedDate}`);
// }
// } catch (error) {
// console.error(`Failed to check or insert record for ${tankName} on ${formattedDate}:`, error);
// }
// }
// }
// console.log("Data generation complete.");
// }
// // Run the data generation function
// generateData();
async function removeDuplicates () {
try {
// Step 1: Find duplicates, considering time and ignoring case for typeofwater
const duplicates = await TankConsumptionOriginalSchema.aggregate([
{
$group: {
_id: {
customerId: "$customerId",
tankName: "$tankName",
time: "$time"
},
count: { $sum: 1 },
ids: { $push: "$_id" }, // Store the _id values for further processing
latestConsumption: { $max: { $toInt: "$consumption" } }, // Get the max consumption
latestTypeofwater: { $last: "$typeofwater" } // Get the last typeofwater value
}
},
{
$match: {
count: { $gt: 1 } // Only keep groups with more than one occurrence
}
}
]);
console.log(`Found ${duplicates.length} groups of duplicates.`);
// Step 2: Prepare delete operations
for (const duplicateGroup of duplicates) {
// Filter the ids based on the maximum time to keep the latest entry
const idsToDelete = duplicateGroup.ids.filter(id => {
return id !== duplicateGroup.ids[0]; // Keep the first, delete the rest
});
for (const id of idsToDelete) {
try {
await TankConsumptionOriginalSchema.deleteOne({ _id: id });
console.log(`Deleted duplicate record with ID: ${id}`);
} catch (deleteError) {
console.error(`Failed to delete record with ID ${id}:`, deleteError);
}
}
}
console.log("Duplicate removal complete.");
} catch (error) {
console.error("Failed to remove duplicates:", error);
}
}
// Run the remove duplicates function
// removeDuplicates();
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({});
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 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;
}
}
// Calculate percentages
const boreConsumptionPercentage = totalBoreCapacity
? ((totalBoreConsumption / totalBoreCapacity) * 100).toFixed(2)
: 0;
const drinkingConsumptionPercentage = totalDrinkingCapacity
? ((totalDrinkingConsumption / totalDrinkingCapacity) * 100).toFixed(2)
: 0;
// 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, "Daily Water Consumption Report", notificationBody);
}
}
console.log("Daily consumption notifications sent successfully.");
} catch (err) {
console.error("Error sending daily consumption notifications:", err);
}
};
// Schedule the cron job to run daily at 9 AM
// cron.schedule(
// "0 9 * * *",
// async () => {
// console.log("Starting daily consumption notification task...");
// await calculateDailyConsumptionAndNotify();
// },
// {
// 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);
}
};
exports.sendUserSetNotifications = async (request, reply) => {
const { customerId, notificationTime, allowNotifications } = request.body;
try {
const user = await User.findOneAndUpdate(
{ customerId },
{ notificationTime, allowNotifications },
{ new: true, upsert: true } // Create user if not exists
);
console.log(`User ${customerId} updated: Notification Time - ${notificationTime}, Allowed - ${allowNotifications}`);
return reply.send({ success: true, user });
} catch (error) {
console.error("Error setting notification time:", error);
return reply.status(500).send({ success: false, message: "Internal server error" });
}
};
exports.sendUserSetLowWaterNotificationsSwitch = async (request, reply) => {
const { customerId, lowWaterAlert } = request.body;
try {
const user = await User.findOneAndUpdate(
{ customerId },
{ lowWaterAlert},
{ new: true, upsert: true } // Create user if not exists
);
console.log(`User ${customerId} updated: Allowed - ${lowWaterAlert}`);
return reply.send({ success: true, user });
} catch (error) {
console.error("Error setting notification time:", error);
return reply.status(500).send({ success: false, message: "Internal server error" });
}
};
exports.sendUserSetCriticallyLowWaterNotificationsSwitch = async (request, reply) => {
const { customerId, criticalLowWaterAlert } = request.body;
try {
const user = await User.findOneAndUpdate(
{ customerId },
{ criticalLowWaterAlert},
{ new: true, upsert: true } // Create user if not exists
);
console.log(`User ${customerId} updated: Allowed - ${criticalLowWaterAlert}`);
return reply.send({ success: true, user });
} catch (error) {
console.error("Error setting notification time:", error);
return reply.status(500).send({ success: false, message: "Internal server error" });
}
};
exports.sendUserManualStartAndStop = async (request, reply) => {
const { customerId, manualStartAndStopNotify } = request.body;
try {
const user = await User.findOneAndUpdate(
{ customerId },
{ manualStartAndStopNotify},
{ new: true, upsert: true } // Create user if not exists
);
console.log(`User ${customerId} updated: Allowed - ${manualStartAndStopNotify}`);
return reply.send({ success: true, user });
} catch (error) {
console.error("Error setting notification time:", error);
return reply.status(500).send({ success: false, message: "Internal server error" });
}
};
exports.sendUserAutomaticStartAndStop = async (request, reply) => {
const { customerId, automaticStartAndStopNotify } = request.body;
try {
const user = await User.findOneAndUpdate(
{ customerId },
{ automaticStartAndStopNotify},
{ new: true, upsert: true } // Create user if not exists
);
console.log(`User ${customerId} updated: Allowed - ${automaticStartAndStopNotify}`);
return reply.send({ success: true, user });
} catch (error) {
console.error("Error setting notification time:", error);
return reply.status(500).send({ success: false, message: "Internal server error" });
}
};
// 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);
// }
// };
const calculateWaterLevelAndNotify = async () => {
try {
const now = moment();
const currentTime = now.format("HH:mm"); // Current time in HH:mm format
console.log(`Current time: ${currentTime}`);
// Get all users who have allowed notifications and have set a notification time
const users = await User.find({ allowNotifications: true, notificationTime: currentTime });
if (users.length === 0) {
console.log("No users to notify at this time.");
return;
}
for (const user of users) {
const { customerId, fcmIds } = user;
if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
console.log(`No valid FCM tokens for customer ID: ${customerId}`);
continue;
}
// Get tanks associated with the user
const tanks = await Tank.find({ customerId });
for (const tank of tanks) {
const {
tankName,
tankLocation,
typeOfWater,
capacity,
waterlevel,
waterlevel_at_midnight,
} = tank;
// 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);
let notificationBody =
`🛢️ Tank Name: ${tankName}\n` +
`🏢 Location: ${tankLocation}\n` +
`💧 Type of Water: ${typeOfWater}\n` +
`Current Water Level: ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n`;
await sendNotification(customerId, fcmIds, "Water Level Update", notificationBody);
console.log("Notification sent for tank:", tankName);
}
}
console.log("Water level notifications processed.");
} catch (err) {
console.error("Error in water level calculation:", err);
}
};
// const calculateLowWaterLevelAndNotify = async () => {
// try {
// const now = moment();
// const currentTime = now.format("HH:mm"); // Current time in HH:mm format
// console.log(`Current time: ${currentTime}`);
// // Get all users who have allowed notifications and have set a notification time
// const users = await User.find({ lowWaterAlert: true });
// if (users.length === 0) {
// console.log("No users to notify at this time.");
// return;
// }
// for (const user of users) {
// const { customerId, fcmIds } = user;
// if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
// console.log(`No valid FCM tokens for customer ID: ${customerId}`);
// continue;
// }
// // Get tanks associated with the user
// const tanks = await Tank.find({ customerId });
// for (const tank of tanks) {
// const {
// tankName,
// tankLocation,
// typeOfWater,
// capacity,
// waterlevel,
// waterlevel_at_midnight,
// } = tank;
// // Remove commas before parsing numbers
// const tankCapacity = parseFloat(capacity.replace(/,/g, '')) || 0;
// const currentWaterLevel = parseFloat(waterlevel.replace(/,/g, '')) || 0;
// if (tankCapacity === 0) {
// console.log(`Skipping tank ${tankName} due to zero capacity`);
// continue;
// }
// const currentWaterLevelPercentage = ((currentWaterLevel / tankCapacity) * 100).toFixed(2);
// // Send notification only if water level is below 15%
// if (currentWaterLevelPercentage < 15) {
// let notificationBody =
// `🛢️ Tank Name: ${tankName}\n` +
// `🏢 Location: ${tankLocation}\n` +
// `💧 Type of Water: ${typeOfWater}\n` +
// `Current Water Level: ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n`;
// await sendNotification(customerId, fcmIds, "Low Water Level Alert", notificationBody);
// console.log("Notification sent for tank:", tankName);
// } else {
// console.log(`Skipping notification for tank ${tankName}, water level is above 15%`);
// }
// }
// }
// console.log("Water level notifications processed.");
// } catch (err) {
// console.error("Error in water level calculation:", err);
// }
// };
// const calculateCriticalLowWaterLevelAndNotify = async () => {
// try {
// const now = moment();
// const currentTime = now.format("HH:mm"); // Current time in HH:mm format
// console.log(`Current time: ${currentTime}`);
// // Get all users who have allowed critical low water notifications
// const users = await User.find({ criticalLowWaterAlert: true });
// if (users.length === 0) {
// console.log("No users to notify at this time.");
// return;
// }
// for (const user of users) {
// const { customerId, fcmIds } = user;
// if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
// console.log(`No valid FCM tokens for customer ID: ${customerId}`);
// continue;
// }
// // Get tanks associated with the user
// const tanks = await Tank.find({ customerId });
// for (const tank of tanks) {
// const {
// tankName,
// tankLocation,
// typeOfWater,
// capacity,
// waterlevel,
// } = tank;
// // Remove commas before parsing numbers
// const tankCapacity = parseFloat(capacity.replace(/,/g, '')) || 0;
// const currentWaterLevel = parseFloat(waterlevel.replace(/,/g, '')) || 0;
// if (tankCapacity === 0) {
// console.log(`Skipping tank ${tankName} due to zero capacity`);
// continue;
// }
// const currentWaterLevelPercentage = ((currentWaterLevel / tankCapacity) * 100).toFixed(2);
// // Send notification only if water level is below 10%
// if (currentWaterLevelPercentage < 10) {
// let notificationBody =
// `🚨 *Critical Low Water Alert!*\n\n` +
// `🛢️ *Tank Name:* ${tankName}\n` +
// `🏢 *Location:* ${tankLocation}\n` +
// `💧 *Type of Water:* ${typeOfWater}\n` +
// `🔴 *Current Water Level:* ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n\n` +
// `⚠️ Immediate action is recommended to avoid water shortage.`;
// await sendNotification(customerId, fcmIds, "Critical Low Water Level Alert", notificationBody);
// console.log(`Critical low water level notification sent for tank: ${tankName}`);
// } else {
// console.log(`Skipping tank ${tankName}, water level is above 10%`);
// }
// }
// }
// console.log("Critical low water level notifications processed.");
// } catch (err) {
// console.error("Error in critical water level calculation:", err);
// }
// };
// Run the function every minute to check if any user needs a notification
// cron.schedule('* * * * *', async () => {
// console.log("Checking for user notification times...");
// await calculateWaterLevelAndNotify();
// }, {
// timezone: "Asia/Kolkata",
// });
//run the every one hour
// cron.schedule('0 */3 * * *', async () => {
// console.log("Checking for user notification times...");
// await calculateLowWaterLevelAndNotify();
// await calculateCriticalLowWaterLevelAndNotify();
// }, {
// timezone: "Asia/Kolkata",
// });
// 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 calculateWaterLevelAndNotify();
// },
// {
// timezone: "Asia/Kolkata", // Specify the timezone
// }
// );
// Schedule a function to run every minute
// cron.schedule('* * * * *', async () => {
// console.log("Checking for user notification times...");
// 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.status.toLowerCase();
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" });
}
};
exports.notificationTiming = async (req, reply) => {
const { customerId, notificationPreference } = req.body;
if (!["never", "always", "6_hours", "8_hours", "1_month"].includes(notificationPreference)) {
return reply.status(400).send({ message: "Invalid preference" });
}
await User.updateOne({ customerId }, { notificationPreference });
return reply.send({ message: "Preference updated successfully" });
}
exports.adjustMeasurement = async (req, reply) => {
try {
const { tankName, measuredHeight } = req.body;
if (!tankName || measuredHeight === undefined) {
return reply.status(400).send({ message: "Tank name and measured height are required." });
}
// Fetch tank details using tankName
const tank = await Tank.findOne({ tankName });
if (!tank) {
return reply.status(404).send({ message: "Tank not found." });
}
const originalHeight = parseFloat(tank.height); // Example: 5.8 feet
const waterCapacityPerCm = parseFloat(tank.waterCapacityPerCm); // Example: 87 L/cm
const actualWaterLevel = parseFloat(tank.waterlevel); // Current water level in tank (liters)
const capacity = parseFloat(tank.capacity.replace(/,/g, ""));
console.log("originalHeight",originalHeight)
console.log("waterCapacityPerCm",waterCapacityPerCm)
console.log("actualWaterLevel",actualWaterLevel)
console.log("capacity",capacity)
// Perform calculations
const heightDifference = originalHeight - measuredHeight;
const heightDifferenceInCm = heightDifference * 30.48; // Convert feet to cm
const calculatedWaterLevel = heightDifferenceInCm * waterCapacityPerCm; // Estimated water level in liters
console.log("heightDifference",heightDifference)
console.log("heightDifferenceInCm",heightDifferenceInCm)
console.log("calculatedWaterLevel",calculatedWaterLevel)
// **Ensure actualWaterLevel and calculatedWaterLevel do not exceed tank capacity**
const boundedActualWaterLevel = Math.min(actualWaterLevel, capacity);
const boundedCalculatedWaterLevel = Math.min(calculatedWaterLevel, capacity);
console.log("boundedActualWaterLevel",boundedActualWaterLevel)
console.log("boundedCalculatedWaterLevel",boundedCalculatedWaterLevel)
// Calculate original and calculated percentages correctly
const originalPercentage = (boundedActualWaterLevel / capacity) * 100;
const calculatedPercentage = (boundedCalculatedWaterLevel / capacity) * 100;
// Calculate percentage difference
const percentageDifference = Math.abs(originalPercentage - calculatedPercentage);
let message;
if (percentageDifference === originalPercentage) {
message = "Tank details and measurement details match.";
} else {
message = "Please check the tank measurement.";
}
reply.send({
status_code: 200,
data: {
tankName,
originalHeight,
measuredHeight,
heightDifference: heightDifference.toFixed(2),
heightDifferenceInCm: heightDifferenceInCm.toFixed(2),
calculatedWaterLevel: calculatedWaterLevel.toFixed(2),
actualWaterLevel: actualWaterLevel.toFixed(2),
originalPercentage: originalPercentage.toFixed(2) + "%",
calculatedPercentage: calculatedPercentage.toFixed(2) + "%",
percentageDifference: percentageDifference.toFixed(2) + "%",
message
}
});
} catch (err) {
reply.status(500).send({ message: err.message });
}
};
exports.validateTankHeight = async (req, reply) => {
try {
const { hardwareId, tankhardwareId } = req.params;
if (!tankhardwareId || !hardwareId) {
return reply.status(400).send({ message: "Both tankhardwareId and hardwareId are required." });
}
// Find tank details from tanksSchema
const tank = await Tank.findOne({ tankhardwareId, hardwareId });
if (!tank) {
return reply.status(404).send({ message: "Tank not found with the given tankhardwareId and hardwareId." });
}
// Find corresponding IoT data from IOttankSchema
const iotTank = await IotData.findOne({ hardwareId, "tanks.tankhardwareId": tankhardwareId });
if (!iotTank) {
return reply.status(404).send({ message: "IoT tank data not found for the given hardwareId and tankhardwareId." });
}
// Convert tank height from feet to cm
const heightInCm = parseFloat(tank.height) * 30.48;
const iotTankHeight = parseFloat(iotTank.tanks.find(t => t.tankhardwareId === tankhardwareId).tankHeight);
console.log("Converted Tank Height (cm):", heightInCm);
console.log("IoT Tank Height (cm):", iotTankHeight);
// Check for extreme values
if (heightInCm < iotTankHeight) {
return reply.status(400).send({
message: "Extreme high values detected! Tank height exceeds IoT data."
});
}
reply.send({
status_code: 200,
message: "Tank height is within the valid range."
});
} catch (err) {
reply.status(500).send({ message: err.message });
}
};
exports.getActualWaterLevelInCm = async (req, reply) => {
try {
const { tankName } = req.params;
if (!tankName) {
return reply.status(400).send({ message: "Tank name is required." });
}
// Fetch tank details using tankName
const tank = await Tank.findOne({ tankName });
if (!tank) {
return reply.status(404).send({ message: "Tank not found." });
}
const actualWaterLevel = parseFloat(tank.waterlevel); // Current water level in liters
const waterCapacityPerCm = parseFloat(tank.waterCapacityPerCm); // Liters per cm
if (!actualWaterLevel || !waterCapacityPerCm) {
return reply.status(400).send({ message: "Tank data is incomplete for conversion." });
}
// Convert actual water level from liters to cm
const actualWaterLevelInCm = actualWaterLevel / waterCapacityPerCm;
reply.send({
status_code: 200,
data: {
tankName,
actualWaterLevel: actualWaterLevel.toFixed(2) + " L",
actualWaterLevelInCm: actualWaterLevelInCm.toFixed(2) + " cm"
}
});
} catch (err) {
reply.status(500).send({ message: err.message });
}
};
exports.compareMeasuredHeight = async (req, reply) => {
try {
const { measuredHeight, tankName } = req.body;
if (!tankName || measuredHeight === undefined) {
return reply.status(400).send({ message: "Tank name and measured height are required." });
}
// Convert measuredHeight to a number
const measuredHeightNum = parseFloat(measuredHeight);
if (isNaN(measuredHeightNum)) {
return reply.status(400).send({ message: "Invalid measuredHeight. It must be a number." });
}
// Fetch tank details using tankName
const tank = await Tank.findOne({ tankName });
if (!tank) {
return reply.status(404).send({ message: "Tank not found." });
}
const actualWaterLevel = parseFloat(tank.waterlevel); // Current water level in liters
const waterCapacityPerCm = parseFloat(tank.waterCapacityPerCm); // Liters per cm
if (isNaN(actualWaterLevel) || isNaN(waterCapacityPerCm)) {
return reply.status(400).send({ message: "Tank data is incomplete for conversion." });
}
// Convert actual water level from liters to cm
const actualWaterLevelInCm = actualWaterLevel / waterCapacityPerCm;
// Calculate difference between measured and actual water level in cm
const heightDifferenceInCm = Math.abs(actualWaterLevelInCm - measuredHeightNum);
let message;
if (heightDifferenceInCm <= 10) {
message = "Manual measurement is match within 10 cm of the sensor data.";
} else {
message = "Manual measurement not matched within range 10cm from the sensor data.";
}
reply.send({
status_code: 200,
data: {
tankName,
measuredHeight: measuredHeightNum.toFixed(2) + " cm",
actualWaterLevelInCm: actualWaterLevelInCm.toFixed(2) + " cm",
heightDifferenceInCm: heightDifferenceInCm.toFixed(2) + " cm",
message
}
});
} catch (err) {
console.error("Error in compareMeasuredHeight:", err);
reply.status(500).send({ message: err.message });
}
};