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.
8070 lines
302 KiB
8070 lines
302 KiB
//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 {
|
|
const customerId = req.query.customerId;
|
|
if (!customerId) {
|
|
return reply.send({ status_code: 400, error: "Missing customerId" });
|
|
}
|
|
|
|
// Use .lean() to get plain JavaScript objects, which are easier to modify
|
|
const tanks = await Tank.find({ customerId }).lean().exec();
|
|
|
|
let totalSwitchCount = 0;
|
|
let totalSensorCount = 0;
|
|
let allSwitchConnectionsDetailed = []; // Array to hold the final consolidated list
|
|
|
|
const transformedDocs = tanks.map((tank) => {
|
|
const inputConnections = tank.connections?.inputConnections || [];
|
|
const currentToTank = tank.tankName || null; // Destination Tank Name
|
|
const currentToLocation = tank.tankLocation || null; // Destination Tank Location
|
|
|
|
// Filter only motor switch connections (raw data)
|
|
const switchConnectionsRaw = inputConnections.filter(conn => conn.inputismotor === true);
|
|
|
|
// Count switches for this tank and add to total
|
|
const switchCount = switchConnectionsRaw.length;
|
|
totalSwitchCount += switchCount;
|
|
|
|
// Count sensor requirement
|
|
if (String(tank.need_sensor).toLowerCase() === "yes") {
|
|
totalSensorCount++;
|
|
}
|
|
|
|
// --- Create the detailed switch connection objects for the consolidated list ---
|
|
const switchConnectionsForThisTankDetailed = switchConnectionsRaw.map(conn => ({
|
|
// Spread all original properties from the switch connection
|
|
from_tank: conn.inputConnections || null, // Get source name from the connection itself
|
|
from_location: conn.input_type || null, // Get source type/location from the connection itself
|
|
to_tank: currentToTank, // Add destination tank name (parent object)
|
|
to_location: currentToLocation // Add destination location (parent object)
|
|
}));
|
|
// Add the detailed connections from *this* tank to the overall list
|
|
allSwitchConnectionsDetailed.push(...switchConnectionsForThisTankDetailed);
|
|
// --- End detailed switch connection creation ---
|
|
|
|
|
|
// Check if any motor is running (motor_status === "2") - keep as is
|
|
const isAnyMotorRunning = inputConnections.some(conn => conn.motor_status === "2");
|
|
|
|
// Map original from_connections for display within the tank object (optional, but your original code did this)
|
|
const fromConnections = inputConnections.map(conn => ({
|
|
from_tank: conn.inputConnections || null,
|
|
from_type: conn.input_type || null,
|
|
}));
|
|
|
|
// Return the transformed tank document for the 'data' array
|
|
return {
|
|
...tank, // Include original tank fields
|
|
connections: { // Keep the connections object structure
|
|
...tank.connections, // Include original connection details (source, input/output arrays)
|
|
switch_count: switchCount, // Keep the count specific to this tank
|
|
// Decide if you want to keep the raw switch_connections here or remove it
|
|
// Keeping it might be useful for context within the specific tank object
|
|
switch_connections: switchConnectionsRaw, // Keep the raw list here
|
|
from_connections: fromConnections, // Keep this derived list here
|
|
},
|
|
all_motor_status: isAnyMotorRunning, // Keep this status flag
|
|
// You might not need these 'to_tank'/'to_location' fields at the root of the tank object anymore
|
|
// as they are now part of the consolidated switch_connections list, but keeping them doesn't hurt.
|
|
to_tank: currentToTank,
|
|
to_location: currentToLocation,
|
|
};
|
|
});
|
|
|
|
// Send the final response with the consolidated list
|
|
reply.send({
|
|
status_code: 200,
|
|
data: transformedDocs, // Array of processed tank objects
|
|
count: transformedDocs.length,
|
|
total_switch_count: totalSwitchCount,
|
|
total_sensor_count: totalSensorCount,
|
|
switch_connections: allSwitchConnectionsDetailed // The new consolidated list
|
|
});
|
|
|
|
} catch (err) {
|
|
console.error("getTank 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" });
|
|
}
|
|
};
|
|
|
|
exports.motoractiontestbeforeqc = async (req, reply) => {
|
|
try {
|
|
|
|
|
|
const { motor_id, action } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
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.` });
|
|
|
|
|
|
|
|
|
|
} 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 });
|
|
// console.log(hw_Id,"hw_Id")
|
|
// console.log(tankhardwareId,"tankhardwareId")
|
|
// console.log(existingTank,"existingTank")
|
|
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}`);
|
|
const now = moment().tz('Asia/Kolkata');
|
|
|
|
if (tankHeight <= 0) {
|
|
// Case 1: First time signal is lost
|
|
if (
|
|
existingTank.slave_status !== "signal_lost1" &&
|
|
existingTank.slave_status !== "not_working1"
|
|
) {
|
|
existingTank.slave_status = "signal_lost1";
|
|
existingTank.slave_disconnected_time = now.format('DD-MMM-YYYY - HH:mm:ss');
|
|
await existingTank.save();
|
|
|
|
console.log(`⚠️ Signal lost for tank [${tankhardwareId}] at ${existingTank.slave_disconnected_time}`);
|
|
return; // Important: do not continue in this cycle
|
|
|
|
} else if (existingTank.slave_status === "signal_lost1") {
|
|
if (!existingTank.slave_disconnected_time) {
|
|
console.log(`❗ Missing slave_disconnected_time despite signal_lost1 for tank [${tankhardwareId}]`);
|
|
return;
|
|
}
|
|
|
|
const lostTime = moment(existingTank.slave_disconnected_time, 'DD-MMM-YYYY - HH:mm:ss');
|
|
const minutesElapsed = now.diff(lostTime, 'minutes');
|
|
|
|
if (minutesElapsed >= 15) {
|
|
existingTank.slave_status = "not_working1";
|
|
existingTank.slave_disconnected_time = now.format('DD-MMM-YYYY - HH:mm:ss');
|
|
await existingTank.save();
|
|
|
|
console.log(`❌ Slave marked as not_working for tank [${tankhardwareId}] at ${existingTank.slave_disconnected_time}`);
|
|
|
|
// Update connected output 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.slave_status = "not_working1";
|
|
await linkedTank.save();
|
|
console.log(`🔗 Linked tank [${linkedTank.tankName}] inputConnection updated to not_working`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
console.log(`⏳ Still within 15-minute grace: ${minutesElapsed} minutes elapsed for tank [${tankhardwareId}]`);
|
|
}
|
|
} else {
|
|
console.log(`⏩ Tank [${tankhardwareId}] already marked as ${existingTank.slave_status}, 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;
|
|
inputConnection. slave_status = "working";
|
|
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);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
//const mqtt = require('mqtt');
|
|
|
|
// Connect to test MQTT broker
|
|
const client2 = mqtt.connect('mqtt://34.100.133.20:1884', {
|
|
clientId: `mqtt_test_${Math.random().toString(16).substr(2, 8)}`,
|
|
clean: true,
|
|
reconnectPeriod: 2000,
|
|
});
|
|
// Sets to track active devices
|
|
const subscribedTopics2 = new Set();
|
|
const activeDevices2 = new Set(); // Keep track of active devices
|
|
|
|
client2.on('connect', () => {
|
|
console.log('✅ Connected to TEST MQTT broker');
|
|
|
|
// Subscribe to the announcement topic
|
|
client2.subscribe('water/iot-data/announce', { qos: 1 }, (err) => {
|
|
if (err) {
|
|
console.error('❌ Failed to subscribe to announce topic:', err);
|
|
} else {
|
|
console.log('📡 Subscribed to water/iot-data/announce');
|
|
}
|
|
});
|
|
});
|
|
|
|
client2.on('message', (topic, message) => {
|
|
console.log(`📩 [${topic}] ${message.toString()}`);
|
|
|
|
try {
|
|
const data = JSON.parse(message.toString());
|
|
|
|
// If announcement message received
|
|
if (topic === 'water/iot-data/announce') {
|
|
if (data.objects && data.objects.hw_Id) {
|
|
const hw_Id = data.objects.hw_Id;
|
|
const deviceTopic = `water/iot-data/${hw_Id}`;
|
|
|
|
if (!subscribedTopics2.has(deviceTopic)) {
|
|
client2.subscribe(deviceTopic, { qos: 1 }, (err) => {
|
|
if (err) {
|
|
console.error(`❌ Failed to subscribe to ${deviceTopic}:`, err);
|
|
} else {
|
|
console.log(`✅ Subscribed to ${deviceTopic}`);
|
|
subscribedTopics2.add(deviceTopic);
|
|
}
|
|
});
|
|
} else {
|
|
console.log(`🔄 Already subscribed to ${deviceTopic}`);
|
|
}
|
|
} else {
|
|
console.error('❌ Invalid announce message, missing hw_Id');
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('❌ Failed to parse message:', err);
|
|
}
|
|
});
|
|
|
|
client2.on('error', (err) => console.error('❌ MQTT Error:', err));
|
|
client2.on('close', () => console.log('⚠️ MQTT2 Connection Closed.'));
|
|
client2.on('offline', () => console.log('⚠️ MQTT Broker Offline.'));
|
|
|
|
|
|
function logSets1() {
|
|
console.log("Subscribed Topics2:", Array.from(subscribedTopics2));
|
|
console.log("Active Devices2:", Array.from(activeDevices2));
|
|
}
|
|
|
|
// Call logSets every 30 seconds
|
|
setInterval(logSets1, 30000);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 });
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
//const ExcelJS = require('exceljs');
|
|
//const IotData = require('../models/IotData'); // adjust the path
|
|
|
|
// async function generateAndSaveTankExcel() {
|
|
// const startDate = "2025-06-03T00:00:00.000Z";
|
|
// const endDate = new Date().toISOString();
|
|
|
|
// const getFilteredData = async (hardwareId) => {
|
|
// const query = {
|
|
// hardwareId,
|
|
// date: {
|
|
// $gte: startDate,
|
|
// $lte: endDate,
|
|
// },
|
|
// };
|
|
|
|
// console.log(`Fetching data for hardwareId: ${hardwareId}`);
|
|
// const results = await IotData.find(query).sort({ date: 1 });
|
|
|
|
// console.log(`Found ${results.length} records for hardwareId ${hardwareId}`);
|
|
|
|
// const data = [];
|
|
|
|
// for (const entry of results) {
|
|
// if (!entry.tanks || !Array.isArray(entry.tanks)) continue;
|
|
|
|
// for (const tank of entry.tanks) {
|
|
// if (tank.tankhardwareId === 'tank-1' || tank.tankhardwareId === 'tank-2') {
|
|
// data.push({
|
|
// hardwareId: entry.hardwareId,
|
|
// tankhardwareId: tank.tankhardwareId,
|
|
// tankHeight: tank.tankHeight,
|
|
// date: tank.date.split('T')[0], // safe because it's a string
|
|
// time: tank.time,
|
|
// });
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// console.log(`Filtered ${data.length} tank records for hardwareId ${hardwareId}`);
|
|
// return data;
|
|
// };
|
|
|
|
// const data140924 = await getFilteredData("140924");
|
|
// const data150924 = await getFilteredData("150924");
|
|
|
|
// const workbook = new ExcelJS.Workbook();
|
|
// const worksheet = workbook.addWorksheet("Tank Data");
|
|
|
|
// worksheet.columns = [
|
|
// { header: "Hardware ID", key: "hardwareId", width: 15 },
|
|
// { header: "Tank ID", key: "tankhardwareId", width: 15 },
|
|
// { header: "Tank Height", key: "tankHeight", width: 15 },
|
|
// { header: "Date", key: "date", width: 15 },
|
|
// { header: "Time", key: "time", width: 15 },
|
|
// ];
|
|
|
|
// const allData = [...data140924, ...data150924];
|
|
|
|
// allData.forEach(row => worksheet.addRow(row));
|
|
|
|
// await workbook.xlsx.writeFile("tank_data.xlsx");
|
|
// console.log("✅ Excel file saved as tank_data.xlsx with rows:", allData.length);
|
|
// }
|
|
|
|
|
|
// generateAndSaveTankExcel();
|
|
|
|
|
|
|
|
|
|
async function publishAllTankMotorsForCustomer(customerId) {
|
|
try {
|
|
const tanks = await Tank.find({ customerId, status: 'active' }).lean();
|
|
|
|
for (const tank of tanks) {
|
|
const { tankName, tankLocation, connections } = tank;
|
|
const inputConnections = connections?.inputConnections || [];
|
|
|
|
for (const conn of inputConnections) {
|
|
if (!conn.motor_id || conn.status !== 'active') continue;
|
|
|
|
let time = 0;
|
|
|
|
if (conn.motor_status === '2') {
|
|
const now = moment().tz('Asia/Kolkata');
|
|
|
|
if (conn.startTime) {
|
|
const start = moment(conn.startTime, 'DD-MMM-YYYY - HH:mm');
|
|
|
|
if (start.isValid()) {
|
|
const hoursElapsed = moment.duration(now.diff(start)).asHours();
|
|
|
|
if (hoursElapsed <= 12) {
|
|
time = Math.floor(moment.duration(now.diff(start)).asMinutes());
|
|
|
|
} else {
|
|
console.log(`⏳ Skipped motor_id ${conn.motor_id} — startTime older than 12 hours`);
|
|
}
|
|
} else {
|
|
console.warn(`⚠️ Invalid startTime format for motor_id ${conn.motor_id}: ${conn.startTime}`);
|
|
}
|
|
} else {
|
|
console.log(`⚠️ startTime is null for motor_id ${conn.motor_id}, sending time = 0`);
|
|
}
|
|
}
|
|
|
|
const payload = {
|
|
tankName,
|
|
tankLocation,
|
|
motor_status: conn.motor_status,
|
|
customerId,
|
|
time,
|
|
};
|
|
|
|
const topic = `water/motor-status/${conn.motor_id}`;
|
|
client.publish(topic, JSON.stringify(payload), { qos: 1 }, (err) => {
|
|
if (err) {
|
|
console.error(`❌ Failed to publish to ${topic}:`, err.message);
|
|
} else {
|
|
console.log(`📤 Published to ${topic}:`, payload);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error(`❌ Error publishing motor data for customer ${customerId}:`, err.message);
|
|
}
|
|
}
|
|
|
|
// 🕒 Call every 30 seconds
|
|
|
|
|
|
// Run every 30 seconds
|
|
setInterval(() => {
|
|
publishAllTankMotorsForCustomer('AWSUSKY4');
|
|
}, 30000);
|
|
|