Resolved conflict in package-lock.json

master^2
ashok 12 months ago
commit 25d489f0c9

2
node_modules/.package-lock.json generated vendored

@ -1,7 +1,7 @@
{ {
"name": "armintatankapi", "name": "armintatankapi",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 2, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"node_modules/@adminjs/design-system": { "node_modules/@adminjs/design-system": {

22809
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -27,6 +27,7 @@
"csvjson": "^5.1.0", "csvjson": "^5.1.0",
"csvtojson": "^2.0.10", "csvtojson": "^2.0.10",
"email-validator": "^2.0.4", "email-validator": "^2.0.4",
"events": "^3.3.0",
"exceljs": "^4.3.0", "exceljs": "^4.3.0",
"fastify": "^3.29.5", "fastify": "^3.29.5",
"fastify-auth": "^1.0.1", "fastify-auth": "^1.0.1",

@ -3,110 +3,229 @@ const boom = require("boom");
const jwt = require('jsonwebtoken') const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt') const bcrypt = require('bcrypt')
const fastify = require("fastify"); const fastify = require("fastify");
const { Tank, MotorData, IotData } = require('../models/tanks') const { Tank, MotorData, IotData } = require('../models/tanks')
const JWT_SECRET = 'your-secret-key';
async function generateCustomerId(role) {
let customerId;
let isUnique = false;
let prefix;
// Set the prefix based on the role
switch (role) {
case 'admin':
prefix = 'AWSAD';
break;
case 'sales':
prefix = 'AWSSL';
break;
case 'store':
prefix = 'AWSST';
break;
default:
throw new Error('Invalid role for customer ID generation');
}
while (!isUnique) {
// Generate a random number or string for the customer ID
const randomId = Math.floor(1000 + Math.random() * 9000).toString(); // Generates a random number between 1000 and 9999
customerId = `${prefix}${randomId}`;
// Check for uniqueness in the Admin collection
const existingAdmin = await Admin.findOne({ customerId });
if (!existingAdmin) {
isUnique = true; // Exit the loop if the customer ID is unique
}
}
// exports.adminSignUp = async (request, reply) => { return customerId;
}
// try {
// const { email, password } = request.body
// // Check if an admin with the same email address already exists exports.adminSignUp = async (request, reply) => {
// const existingAdmin = await Admin.findOne({ email }) try {
const { phone, username, password, role } = request.body;
// if (existingAdmin) { if (!username || username.trim() === '') {
// return reply.status(400).send({ message: 'Email already registered' }) return reply.status(400).send({ message: 'Username is required' });
// } }
// // Hash the password using bcrypt // Validate role
// const hashedPassword = await bcrypt.hash(password, 10) if (!role || !['admin', 'sales', 'store'].includes(role)) {
return reply.status(400).send({ message: 'Invalid role. Must be either admin, sales, or store' });
}
// // Create a new admin object with the hashed password
// const admin = new Admin({ email, password: hashedPassword })
// // Save the new admin to the database
// await admin.save()
// // Generate a JWT token for the new admin // Check if an admin with the same phone number or username already exists
// // const token = jwt.sign({ email: admin.email }, 'secret') // const existingAdminUsername = await Admin.findOne({ username });
// const existingAdmin = await Admin.findOne({ phone });
// // // Return the token to the client // if (existingAdmin) {
// // return { token } // return reply.status(400).send({ message: 'Phone already registered' });
// reply.send({message : "Admin Account Created Sucessfully"})
// } catch (err) {
// reply.status(500).send({ message: err.message })
// } // }
// if (existingAdminUsername) {
// return reply.status(400).send({ message: 'Username already registered' });
// } // }
exports.adminSignUp = async (request, reply) => { // Hash the password using bcrypt
const hashedPassword = await bcrypt.hash(password, 10);
try { const customerId = await generateCustomerId(role); // Assuming you have this function defined elsewhere
const { email, password } = request.body //const building = 'ADMIN'; // You can customize this logic to derive from a parameter or a default value
//const customerId = `AWSU${building}${c_id}`; // Construct the customer ID
// Check if the email address is valid // Create a new admin object with the hashed password and role
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ const admin = new Admin({ phone, username, password: hashedPassword, customerId, role });
if (!emailRegex.test(email)) {
return reply.status(400).send({ message: 'Invalid email address' })
}
// Check if an admin with the same email address already exists // Save the new admin to the database
const existingAdmin = await Admin.findOne({ email }) await admin.save();
if (existingAdmin) { reply.send({ message: 'Admin Account Created Successfully' });
return reply.status(400).send({ message: 'Email already registered' }) } catch (err) {
reply.status(500).send({ message: err.message });
} }
};
// Hash the password using bcrypt
const hashedPassword = await bcrypt.hash(password, 10)
// Create a new admin object with the hashed password // Admin Login Function (With Phone Number)
const admin = new Admin({ email, password: hashedPassword }) exports.adminLogin = async (request, reply) => {
try {
const { phone, password } = request.body;
// Save the new admin to the database // Check if an admin with the phone number exists
await admin.save() const admin = await Admin.findOne({ phone });
if (!admin) {
return reply.status(401).send({ message: 'Invalid phone number or password' });
}
// Generate a JWT token for the new admin // Compare the password entered by the user with the hashed password stored in the database
// const token = jwt.sign({ email: admin.email }, 'secret') const isPasswordValid = await bcrypt.compare(password, admin.password);
// // Return the token to the client if (!isPasswordValid) {
// return { token } return reply.status(401).send({ message: 'Invalid phone number or password' });
reply.send({message : "Admin Account Created Sucessfully"})
} catch (err) {
reply.status(500).send({ message: err.message })
} }
// Generate a JWT token for the authenticated admin
const token = jwt.sign({ phone: admin.phone, role: 'admin' }, JWT_SECRET, { expiresIn: '1h' });
return reply.send({ token });
} catch (err) {
reply.status(500).send({ message: err.message });
} }
};
exports.adminLogin = async (request, reply) => { exports.salesStoreLogin = async (request, reply) => {
try { try {
const { email, password } = request.body const { phone, password, role } = request.body;
// Check if an admin with the email address exists // Check if a user (sales or store) with the phone number and role exists
const admin = await Admin.findOne({ email }) const user = await Admin.findOne({ phone, role });
if (!admin) { if (!user) {
return reply.status(401).send({ message: 'Invalid email or password' }) return reply.status(401).send({ message: 'Invalid phone number, password, or role' });
} }
// Compare the password entered by the user with the hashed password stored in the database // Compare the password entered by the user with the hashed password stored in the database
const isPasswordValid = await bcrypt.compare(password, admin.password) const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) { if (!isPasswordValid) {
return reply.status(401).send({ message: 'Invalid email or password' }) return reply.status(401).send({ message: 'Invalid phone number, password, or role' });
} }
// Generate a JWT token for the authenticated admin // Generate a JWT token for the authenticated user (with role sales or store)
const token = jwt.sign({ email: admin.email }, 'secret') const token = jwt.sign({ phone: user.phone, role: user.role }, JWT_SECRET, { expiresIn: '1h' });
// Return the token to the client return reply.send({ token });
return { token }
} catch (err) { } catch (err) {
reply.status(500).send({ message: err.message }) reply.status(500).send({ message: err.message });
}
};
exports.getUsersByRole = async (request, reply) => {
try {
const { role } = request.params;
// Ensure the role is either 'sales' or 'store'
if (!['sales', 'store'].includes(role)) {
return reply.status(400).send({ message: 'Invalid role. Must be either sales or store.' });
}
// Find users with the specific role (sales or store)
const users = await Admin.find({ role });
// Send back the list of users
reply.send(users);
} catch (err) {
reply.status(500).send({ message: err.message });
}
};
exports.getUserByCustomerId = async (request, reply) => {
try {
const { customerId } = request.params;
// Check if customerId is provided
if (!customerId) {
return reply.status(400).send({ message: 'Customer ID is required' });
}
// Fetch the user from the database
const user = await Admin.findOne({ customerId });
// If user not found, return a 404 response
if (!user) {
return reply.status(404).send({ message: 'User not found' });
}
// Return the user data
return reply.send(user);
} catch (err) {
return reply.status(500).send({ message: err.message });
}
};
exports.createUser = async (request, reply) => {
const { phone, password, role } = request.body;
// Validate role (only sales or store)
if (!['sales', 'store'].includes(role)) {
return reply.status(400).send({ message: 'Invalid role. Must be either sales or store' });
} }
try {
const existingUser = await Admin.findOne({ phone });
if (existingUser) {
return reply.status(400).send({ message: 'User with this phone number already exists' });
} }
// Hash the password
const hashedPassword = await bcrypt.hash(password, 10);
// Create the new user
const newUser = new Admin({
phone,
password: hashedPassword,
role,
});
await newUser.save();
return reply.send({ message: 'User created successfully' });
} catch (err) {
reply.status(500).send({ message: err.message });
}
};
exports.integratingHardwareidToTank = async (request, reply) => { exports.integratingHardwareidToTank = async (request, reply) => {
@ -120,8 +239,3 @@ exports.adminSignUp = async (request, reply) => {
} }
} }

@ -10,7 +10,8 @@ const fastify = require("fastify")({
const cron = require('node-cron'); const cron = require('node-cron');
const moment = require('moment'); const moment = require('moment');
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
async function deleteOldRecords() { async function deleteOldRecords() {
const SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000; const SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
const sevenDaysAgo = new Date(Date.now() - SEVEN_DAYS_IN_MILLISECONDS); const sevenDaysAgo = new Date(Date.now() - SEVEN_DAYS_IN_MILLISECONDS);
@ -1320,28 +1321,83 @@ admin.initializeApp({
credential: admin.credential.cert(serviceAccount), credential: admin.credential.cert(serviceAccount),
}); });
// // Handle motor start event
// eventEmitter.on('motorStart', async (fcmTokens) => {
// await sendNotification(fcmTokens, 'Motor Started', 'The motor has been started successfully.');
// });
// // Handle motor stop event
// eventEmitter.on('motorStop', async (fcmTokens) => {
// await sendNotification(fcmTokens, 'Motor Stopped', 'The motor has been stopped successfully.');
// });
// // Handle low water level event
// eventEmitter.on('lowWaterLevel', async (fcmTokens) => {
// await sendNotification(fcmTokens, 'Low Water Level', 'The water level is below 20%.');
// });
// // Handle high water level event
// eventEmitter.on('highWaterLevel', async (fcmTokens) => {
// await sendNotification(fcmTokens, 'High Water Level', 'The water level has reached above 90%.');
// });
// Handle motor start event with timestamp
eventEmitter.on('motorStart', async (fcmTokens, timestamp, motorId, waterLevel) => {
await sendNotification(fcmTokens, 'Motor Started', `Motor ID: ${motorId} started successfully at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`);
});
// Emit motor stop event with motorId
eventEmitter.on('motorStop', async (fcmTokens, timestamp, motorId, waterLevel) => {
await sendNotification(fcmTokens, 'Motor Stopped', `Motor ID: ${motorId} stopped successfully at ${timestamp}.Current Water Level: ${waterLevel} Ltrs`);
});
// Emit low water level event with motorId
eventEmitter.on('lowWaterLevel', async (fcmTokens, timestamp, motorId, waterLevel) => {
await sendNotification(fcmTokens, 'Low Water Level', `Motor ID: ${motorId}, water level dropped below 20% at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`);
});
// 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`);
});
// 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) => { const sendNotification = async (fcmTokens, title, body) => {
if (!Array.isArray(fcmTokens) || fcmTokens.length === 0) { if (!Array.isArray(fcmTokens) || fcmTokens.length === 0) {
console.error('No FCM tokens provided.'); console.error('No FCM tokens provided.');
return; return;
} }
for (const token of fcmTokens) {
const message = { const message = {
tokens: fcmTokens, token: token,
notification: { notification: {
title: title, title: title,
body: body, body: body,
}, },
data: {
target: 'tank_levels',
},
}; };
try { try {
const response = await admin.messaging().sendMulticast(message); const response = await admin.messaging().send(message); // Send each message individually
console.log('Notification sent successfully:', response); console.log('Notification sent successfully:', response);
} catch (error) { } catch (error) {
console.error('Error sending notification:', error); console.error(`Failed to send notification to token ${token}:`, error);
}
} }
}; };
// const sendPushNotification = async (registrationToken, title, body) => { // const sendPushNotification = async (registrationToken, title, body) => {
// const message = { // const message = {
// notification: { // notification: {
@ -1383,35 +1439,329 @@ exports.publishMotorStopStatus = async (motor_id, motor_stop_status) => {
}; };
const stat_stop_intervals = {}; 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);
// }
// };
exports.motorAction = async (req, reply) => { exports.motorAction = async (req, reply) => {
try { try {
const customerId = req.params.customerId; const customerId = req.params.customerId;
const action = req.body.action; const action = req.body.action;
const motorId = req.body.motor_id; const motorId = req.body.motor_id;
const start_instance_id = req.body.start_instance_id const start_instance_id = req.body.start_instance_id;
console.log(req.body.startTime)
// Define thresholds for water levels
const lowWaterThreshold = 20; // Low water level percentage threshold
const highWaterThreshold = 90; // High water level percentage threshold
// Ensure motor_id is provided // Ensure motor_id is provided
if (!motorId) { if (!motorId) {
throw new Error("Motor ID is required."); throw new Error("Motor ID is required.");
} }
const users = await User.find({ customerId: customerId }); // Get user FCM tokens
const users = await User.find({ customerId });
const fcmToken = users.map(user => user.fcmId).filter(fcmId => fcmId); const fcmToken = users.map(user => user.fcmId).filter(fcmId => fcmId);
console.log(fcmToken)
const receiverTank = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
console.log(receiverTank)
const currentWaterLevel = parseInt(receiverTank.waterlevel, 10);
// Determine the motor stop status based on the action // Determine the motor stop status based on the action
let motorStopStatus; let motorStopStatus;
if (action === "start") { if (action === "start") {
motorStopStatus = "2"; // If action is start, set stop status to "2" motorStopStatus = "2"; // If action is start, set stop status to "2"
emitWithTimestamp('motorStart', fcmToken, motorId, currentWaterLevel);
} else if (action === "stop") { } else if (action === "stop") {
motorStopStatus = "1"; // If action is stop, set stop status to "1" motorStopStatus = "1"; // If action is stop, set stop status to "1"
emitWithTimestamp('motorStop', fcmToken, motorId, currentWaterLevel);
} else { } else {
throw new Error("Invalid action provided."); throw new Error("Invalid action provided.");
} }
// Update the motor stop status immediately if action is stop // If action is stop, immediately update motor status and perform stop operations
if (action === "stop") { if (action === "stop") {
// Update the motor stop status and other fields
await Tank.updateOne( await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId }, { customerId, "connections.inputConnections.motor_id": motorId },
{ {
@ -1432,7 +1782,6 @@ exports.motorAction = async (req, reply) => {
(async () => { (async () => {
await delay(300000); 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 }); const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
if (motorData) { if (motorData) {
const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() }); const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
@ -1440,6 +1789,7 @@ exports.motorAction = async (req, reply) => {
const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10); const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10); const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
const totalwaterpumped = quantityDelivered + water_pumped_till_now; const totalwaterpumped = quantityDelivered + water_pumped_till_now;
await Tank.findOneAndUpdate( await Tank.findOneAndUpdate(
{ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() }, { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
{ $set: { total_water_added_from_midnight: totalwaterpumped } } { $set: { total_water_added_from_midnight: totalwaterpumped } }
@ -1455,14 +1805,11 @@ exports.motorAction = async (req, reply) => {
} }
} }
); );
} }
})(); })();
// Return here to ensure the rest of the code is not executed for the stop action return; // Return early to avoid executing the start logic
return;
} else { } else {
// Update the motor stop status to "2" for start action
await Tank.updateOne( await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId }, { customerId, "connections.inputConnections.motor_id": motorId },
{ $set: { "connections.inputConnections.$.motor_stop_status": "2" } } { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
@ -1472,15 +1819,10 @@ exports.motorAction = async (req, reply) => {
// Check threshold settings if action is start // Check threshold settings if action is start
if (action === "start") { if (action === "start") {
if (req.body.threshold_type === "time") { if (req.body.threshold_type === "time") {
// If threshold type is time, update threshold time // Create a new MotorData entry
// await Tank.updateOne( const receiverTank = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
// { 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({ const newMotorData = new MotorData({
customerId: customerId, customerId,
motor_id: motorId, motor_id: motorId,
start_instance_id: start_instance_id, start_instance_id: start_instance_id,
supplierTank: req.body.from, supplierTank: req.body.from,
@ -1488,35 +1830,36 @@ exports.motorAction = async (req, reply) => {
supplier_type: req.body.from_type, supplier_type: req.body.from_type,
receiver_type: req.body.to_type, receiver_type: req.body.to_type,
startTime: req.body.startTime, startTime: req.body.startTime,
receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10) receiverInitialwaterlevel: parseInt(receiverTank.waterlevel, 10)
}); });
await newMotorData.save(); await newMotorData.save();
// Update the tank connections with start time and threshold time
for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
this.publishMotorStopStatus(motorId, motorStopStatus); this.publishMotorStopStatus(motorId, motorStopStatus);
for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) { for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId); const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
if (index !== -1) { if (index !== -1) {
await Tank.updateOne( await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId }, { 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 } } {
$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 thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
const intervalId = setInterval(async () => { const intervalId = setInterval(async () => {
const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() }); const supplierTank = 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 currentWaterLevel = parseInt(supplierTank.waterlevel, 10);
//console.log(splr_tank_info3_waterlevel,"splr_tank_info3_waterlevel") const currentWaterPercentage = (currentWaterLevel / parseInt(supplierTank.capacity.replace(/,/g, ''), 10)) * 100;
const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
// const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity, 10); if (new Date() >= thresholdTime || currentWaterPercentage <= lowWaterThreshold) {
// 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( await Tank.updateOne(
{ customerId, "connections.inputConnections.motor_id": motorId }, { customerId, "connections.inputConnections.motor_id": motorId },
{ {
@ -1528,27 +1871,29 @@ exports.motorAction = async (req, reply) => {
} }
} }
); );
emitWithTimestamp('lowWaterLevel', fcmToken); // Emit low water level notification
clearInterval(intervalId); clearInterval(intervalId);
this.publishMotorStopStatus(motorId, "1"); this.publishMotorStopStatus(motorId, "1");
await delay(300000); await delay(300000);
const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id }); const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
if (motorData) { if (motorData) {
const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() }); const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10); const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10); const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10); const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
const totalwaterpumped = quantityDelivered + water_pumped_till_now 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 Tank.findOneAndUpdate(
{ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
{ $set: { total_water_added_from_midnight: totalwaterpumped } }
);
await MotorData.updateOne( await MotorData.updateOne(
{ customerId, motor_id: motorId, start_instance_id: start_instance_id }, { customerId, motor_id: motorId, start_instance_id: start_instance_id },
{ {
$set: { $set: {
stopTime:stopTime, stopTime: req.body.stopTime,
receiverfinalwaterlevel: receiverFinalWaterLevel.toString(), receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
quantity_delivered: quantityDelivered.toString() quantity_delivered: quantityDelivered.toString()
} }
@ -1556,7 +1901,14 @@ exports.motorAction = async (req, reply) => {
); );
} }
} }
}, 60000);
// Check for high water level and send notification
if (currentWaterPercentage >= highWaterThreshold) {
emitWithTimestamp('highWaterLevel', fcmToken); // Emit high water level notification
}
}, 60000); // Check every minute
}
} else if (req.body.threshold_type === "litres") { } else if (req.body.threshold_type === "litres") {
console.log("entered litres") console.log("entered litres")
const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() }); const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
@ -1653,14 +2005,13 @@ exports.motorAction = async (req, reply) => {
); );
} }
} }
}, 20000); // Check water level every minute }, 20000);
} }
} }
// Respond with success message // Respond with success message
reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` }); reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
} catch (err) { } catch (err) {
// Handle errors
throw boom.boomify(err); throw boom.boomify(err);
} }
}; };
@ -3440,7 +3791,7 @@ const updatetotalConsumptiontillmidnight = async () => {
const formattedDate = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm'); const formattedDate = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
// Check if the record already exists // Check if the record already exists
const existingRecord = await TankConsumptionSchema.findOne({ const existingRecord = await TankConsumptionOriginalSchema.findOne({
customerId: tank.customerId, customerId: tank.customerId,
tankName: tank.tankName, tankName: tank.tankName,
tankLocation: tank.tankLocation, tankLocation: tank.tankLocation,
@ -3449,7 +3800,7 @@ const updatetotalConsumptiontillmidnight = async () => {
if (!existingRecord) { if (!existingRecord) {
// Create and save the new document if it doesn't exist // Create and save the new document if it doesn't exist
const newTankConsumption = new TankConsumptionSchema({ const newTankConsumption = new TankConsumptionOriginalSchema({
customerId: tank.customerId, customerId: tank.customerId,
tankName: tank.tankName, tankName: tank.tankName,
tankLocation: tank.tankLocation, tankLocation: tank.tankLocation,
@ -3475,7 +3826,7 @@ const updatetotalConsumptiontillmidnight = async () => {
clearConsumptionSchedule(); clearConsumptionSchedule();
// Schedule the task to run every day at 12:49 PM IST and store the reference // Schedule the task to run every day at 12:49 PM IST and store the reference
consumptionTask = cron.schedule('32 15 * * *', updatetotalConsumptiontillmidnight, { consumptionTask = cron.schedule('50 23 * * *', updatetotalConsumptiontillmidnight, {
timezone: "Asia/Kolkata" timezone: "Asia/Kolkata"
}); });
@ -3925,7 +4276,7 @@ exports.getBlockData = async (req, reply) => {
const mqtt = require('mqtt'); const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://35.207.198.4:1883'); // Connect to MQTT broker const client = mqtt.connect('mqtt://35.207.198.4:1884'); // Connect to MQTT broker
client.on('connect', () => { client.on('connect', () => {
console.log('Connected to MQTT broker'); console.log('Connected to MQTT broker');
@ -4057,5 +4408,74 @@ client.on('message', async (topic, message) => {
// }; // };
exports.consumptionofparticulartank = async (request, reply) => {
try {
const { customerId } = request.params;
const { startDate, stopDate, tankName, tankLocation, block } = request.body;
// Ensure dates are formatted or parsed correctly for the query
const start = startDate;
const end = stopDate;
// 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);
// Find consumption records for the tank between the given dates
const tankConsumptions = await TankConsumptionOriginalSchema.find({
customerId,
tankName,
tankLocation: tankLocation,
time: {
$gte: start,
$lte: end,
},
});
// Calculate total consumption from records
const total_consumption_from_records = tankConsumptions.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,
};
// Send the response, including both total consumption and tankConsumptions data
reply.send({
status_code: 200,
tankData,
totalConsumption: consumption,
consumptionRecords: tankConsumptions, // Add the consumption records here
});
} catch (err) {
throw boom.boomify(err);
}
};

@ -1,16 +1,38 @@
const mongoose = require('mongoose') const mongoose = require('mongoose')
const adminSchema = new mongoose.Schema({ const adminSchema = new mongoose.Schema({
email: {
phone: {
type: String, type: String,
required: true, required: true,
unique: true, //unique: true,
lowercase: true },
username: {
type: String,
required: true,
// unique: true,
}, },
password: { password: {
type: String, type: String,
required: true required: true
} },
role: {
type: String,
enum: ['admin', 'sales', 'store'],
default: 'sales',
},
customerId: {
type: String,
required: true, // Customer ID is now required
unique: true,
},
date: {
type: Date,
default: Date.now,
},
}) })
const Admin = mongoose.model('Admin', adminSchema) const Admin = mongoose.model('Admin', adminSchema)

@ -3,19 +3,23 @@ const adminController = require('../controllers/admincontroller')
module.exports = function (fastify, opts, next) { module.exports = function (fastify, opts, next) {
fastify.route({ fastify.route({
method: "POST", method: "POST",
url: "/api/adminSignup", url: "/api/adminSignup",
schema: { schema: {
tags: ["Admin"], tags: ["Admin"],
description: "This is for cretae New Admin Account", description: "This is for creating a new Admin/sales/store Account",
summary: "This is for cretae New Admin Account", summary: "This is for creating a new Admin/sales/store Account",
body: { body: {
type: "object", type: "object",
required: ["phone", "username", "password", "role"], // Add role to required fields
properties: { properties: {
email: { type: "string" }, phone: { type: "string" },
password: { type: "string" }, password: { type: "string" },
username: { type: "string" },
role: { type: "string", enum: ["admin", "sales", "store"] }, // Define allowed roles
}, },
}, },
security: [ security: [
@ -24,11 +28,10 @@ fastify.route({
}, },
], ],
}, },
handler: adminController.adminSignUp, handler: adminController.adminSignUp,
}); });
fastify.post("/api/adminLogin", { fastify.post("/api/adminLogin", {
schema: { schema: {
description: "This is for Login Admin", description: "This is for Login Admin",
@ -36,9 +39,9 @@ fastify.route({
summary: "This is for Login Admin", summary: "This is for Login Admin",
body: { body: {
type: "object", type: "object",
required: ["email", "password"], required: ["phone", "password"],
properties: { properties: {
email: { type: "string" }, phone : { type: "string" },
password: { type: "string" }, password: { type: "string" },
}, },
}, },
@ -46,6 +49,100 @@ fastify.route({
handler: adminController.adminLogin, handler: adminController.adminLogin,
}); });
fastify.post("/api/salesStoreLogin", {
schema: {
description: "Login for sales/store users",
tags: ["Sales/Store Login"],
summary: "Login for sales/store users",
body: {
type: "object",
required: ["phone", "password", "role"],
properties: {
phone : { type: "string" },
password: { type: "string" },
role: { type: "string", enum: ["sales", "store"] }
},
},
},
handler: adminController.salesStoreLogin,
});
fastify.get("/api/getUsersByRole/:role", {
schema: {
description: "Get list of users by role (sales/store)",
tags: ["Sales/Store Users"],
summary: "Get list of users by role",
params: {
type: "object",
properties: {
role: { type: "string", enum: ["sales", "store"] },
},
required: ["role"],
},
response: {
200: {
type: "array",
items: {
type: "object",
properties: {
phone: { type: "string" },
username: { type: "string" },
role: { type: "string" },
date: { type: "string", format: "date-time" }
}
}
}
}
},
handler: adminController.getUsersByRole,
});
fastify.route({
method: "GET",
url: "/api/users/:customerId", // Use path parameters for customerId
schema: {
tags: ["Admin"],
description: "Retrieve user information by customerId",
summary: "Get user by customerId",
params: {
type: "object",
required: ["customerId"],
properties: {
customerId: { type: "string" },
},
},
security: [
{
basicAuth: [],
},
],
},
handler: adminController.getUserByCustomerId, // Link the handler function
});
// fastify.post("/api/createUser", {
// schema: {
// description: "This is for Create sale/store",
// tags: ["createUser for sale/sore"],
// summary: "This is for Create sale/store",
// body: {
// type: "object",
// required: ["phone", "password", "role"],
// properties: {
// phone : { type: "string" },
// password: { type: "string" },
// role: { type: "string", enum: ["sales", "store"] }
// },
// },
// },
// handler: adminController.createUser,
// });
fastify.post("/api/integratingHardwareidToTank", { fastify.post("/api/integratingHardwareidToTank", {
schema: { schema: {
description: "This is for integrating hardwareId with tank", description: "This is for integrating hardwareId with tank",

@ -1001,6 +1001,43 @@ module.exports = function (fastify, opts, next) {
handler: tanksController.getBlockData, handler: tanksController.getBlockData,
}); });
fastify.route({
method: "PUT",
url: "/api/consumptionofparticulartank/:customerId",
schema: {
tags: ["Tank"],
summary: "This is for getting consumption of a particular tank",
params: {
required: ["customerId"],
type: "object",
properties: {
customerId: {
type: "string",
description: "Customer ID",
},
},
},
body: {
type: "object",
properties: {
tankName: { type: "string", description: "Tank name" },
tankLocation: { type: "string", description: "Tank location" },
startDate: { type: "string", description: "Start date" },
stopDate: { type: "string", description: "Stop date" },
block: { type: "string", description: "Block name" },
},
},
security: [
{
basicAuth: [],
},
],
},
// preHandler: fastify.auth([fastify.authenticate]),
handler: tanksController.consumptionofparticulartank,
});
next(); next();
} }

Loading…
Cancel
Save