|
|
@ -2848,7 +2848,203 @@ exports.getMasterSlaveSummary = async (req, reply) => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getPendingMasterSlaveSummary = async (req, reply) => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const { customerId } = req.params;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!customerId) {
|
|
|
|
|
|
|
|
return reply.status(400).send({ error: "customerId is required" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch all master devices from Insensors
|
|
|
|
|
|
|
|
const masters = await Insensors.find({ customerId, type: "master" }).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch orders to build orderMap: hardwareId → { masterName, location, work_status }
|
|
|
|
|
|
|
|
const orders = await Order.find({ customerId }).lean();
|
|
|
|
|
|
|
|
const orderMap = {}; // key: hardwareId
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
orders.forEach(order => {
|
|
|
|
|
|
|
|
if (Array.isArray(order.master_connections)) {
|
|
|
|
|
|
|
|
order.master_connections.forEach(connection => {
|
|
|
|
|
|
|
|
if (connection.hardwareId) {
|
|
|
|
|
|
|
|
orderMap[connection.hardwareId] = {
|
|
|
|
|
|
|
|
masterName: connection.master_name || null,
|
|
|
|
|
|
|
|
location: connection.location || null,
|
|
|
|
|
|
|
|
work_status: connection.work_status || null
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const result = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const master of masters) {
|
|
|
|
|
|
|
|
const orderInfo = orderMap[master.hardwareId] || {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Only keep masters where work_status === 'active'
|
|
|
|
|
|
|
|
if (orderInfo.work_status !== 'pending') {
|
|
|
|
|
|
|
|
continue; // skip this master
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Prefer Insensors name/location, fallback to order info
|
|
|
|
|
|
|
|
const masterName = master.masterName || orderInfo.masterName || null;
|
|
|
|
|
|
|
|
const location = master.location || orderInfo.location || null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch latest GSM data
|
|
|
|
|
|
|
|
const latestGsmData = await IotData.findOne({ hardwareId: master.hardwareId })
|
|
|
|
|
|
|
|
.sort({ date: -1, time: -1 })
|
|
|
|
|
|
|
|
.lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let connectedGsmDate = null;
|
|
|
|
|
|
|
|
let connectedGsmTime = null;
|
|
|
|
|
|
|
|
let gsmStatus = "unknown";
|
|
|
|
|
|
|
|
let gsmLastDisconnect = master.gsm_last_disconnect_time || null;
|
|
|
|
|
|
|
|
let gsmLastCheckTime = master.gsm_last_check_time || null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (latestGsmData?.date && latestGsmData?.time) {
|
|
|
|
|
|
|
|
const indiaTime = moment.tz(
|
|
|
|
|
|
|
|
`${moment(latestGsmData.date).format("YYYY-MM-DD")} ${latestGsmData.time}`,
|
|
|
|
|
|
|
|
"YYYY-MM-DD HH:mm:ss",
|
|
|
|
|
|
|
|
"Asia/Kolkata"
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
connectedGsmDate = indiaTime.format("DD-MM-YYYY");
|
|
|
|
|
|
|
|
connectedGsmTime = indiaTime.format("HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
|
|
|
const diffInMinutes = now.diff(indiaTime, "minutes");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gsmStatus = diffInMinutes <= 1 ? "connected" : "disconnected";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gsmStatus === "disconnected") {
|
|
|
|
|
|
|
|
gsmLastDisconnect = `${connectedGsmDate} ${connectedGsmTime}`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update master Insensors record
|
|
|
|
|
|
|
|
await Insensors.updateOne(
|
|
|
|
|
|
|
|
{ hardwareId: master.hardwareId },
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
$set: {
|
|
|
|
|
|
|
|
connected_status: gsmStatus,
|
|
|
|
|
|
|
|
connected_gsm_date: connectedGsmDate,
|
|
|
|
|
|
|
|
connected_gsm_time: connectedGsmTime,
|
|
|
|
|
|
|
|
gsm_last_check_time: gsmLastCheckTime,
|
|
|
|
|
|
|
|
gsm_last_disconnect_time: gsmLastDisconnect
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Process connected slaves
|
|
|
|
|
|
|
|
const connectedSlaves = [];
|
|
|
|
|
|
|
|
const slaves = await Insensors.find({ connected_to: master.hardwareId, type: "slave" }).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const slave of slaves) {
|
|
|
|
|
|
|
|
const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
|
|
|
let connectedLoraDate = null;
|
|
|
|
|
|
|
|
let connectedLoraTime = null;
|
|
|
|
|
|
|
|
let loraStatus = "disconnected";
|
|
|
|
|
|
|
|
let loraLastDisconnect = slave.lora_last_disconnect_time || null;
|
|
|
|
|
|
|
|
let loraLastCheckTime = slave.lora_last_check_time || null;
|
|
|
|
|
|
|
|
let typeOfWater = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch latest slave IotData (using master hardwareId because slave data comes there)
|
|
|
|
|
|
|
|
const slaveIot = await IotData.findOne({ hardwareId: slave.connected_to })
|
|
|
|
|
|
|
|
.sort({ date: -1, time: -1 })
|
|
|
|
|
|
|
|
.lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (slaveIot?.tanks?.length && slave.tankhardwareId) {
|
|
|
|
|
|
|
|
const matchedTank = slaveIot.tanks.find(t => t.tankhardwareId === slave.tankhardwareId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (matchedTank) {
|
|
|
|
|
|
|
|
const indiaTime = moment.tz(
|
|
|
|
|
|
|
|
`${moment(matchedTank.date).format("YYYY-MM-DD")} ${matchedTank.time}`,
|
|
|
|
|
|
|
|
"YYYY-MM-DD HH:mm:ss",
|
|
|
|
|
|
|
|
"Asia/Kolkata"
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
connectedLoraDate = indiaTime.format("DD-MM-YYYY");
|
|
|
|
|
|
|
|
connectedLoraTime = indiaTime.format("HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const diffMinutes = now.diff(indiaTime, "minutes");
|
|
|
|
|
|
|
|
const tankHeight = parseFloat(matchedTank.tankHeight) || 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loraStatus = (tankHeight > 0 && diffMinutes <= 1) ? "connected" : "disconnected";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (loraStatus === "disconnected") {
|
|
|
|
|
|
|
|
loraLastDisconnect = `${connectedLoraDate} ${connectedLoraTime}`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enrich with tank typeOfWater if exists
|
|
|
|
|
|
|
|
const matchedTankDetails = await Tank.findOne({
|
|
|
|
|
|
|
|
customerId,
|
|
|
|
|
|
|
|
tankhardwareId: slave.tankhardwareId
|
|
|
|
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (matchedTankDetails?.typeOfWater) {
|
|
|
|
|
|
|
|
typeOfWater = matchedTankDetails.typeOfWater;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update slave Insensors record
|
|
|
|
|
|
|
|
await Insensors.updateOne(
|
|
|
|
|
|
|
|
{ hardwareId: slave.hardwareId },
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
$set: {
|
|
|
|
|
|
|
|
connected_status: loraStatus,
|
|
|
|
|
|
|
|
connected_lora_date: connectedLoraDate,
|
|
|
|
|
|
|
|
connected_lora_time: connectedLoraTime,
|
|
|
|
|
|
|
|
lora_last_check_time: loraLastCheckTime,
|
|
|
|
|
|
|
|
lora_last_disconnect_time: loraLastDisconnect
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
connectedSlaves.push({
|
|
|
|
|
|
|
|
hardwareId: slave.hardwareId,
|
|
|
|
|
|
|
|
tankhardwareId: slave.tankhardwareId || null,
|
|
|
|
|
|
|
|
tankName: slave.tankName || null,
|
|
|
|
|
|
|
|
location: slave.tankLocation || null,
|
|
|
|
|
|
|
|
connected_status: loraStatus,
|
|
|
|
|
|
|
|
connected_lora_date: connectedLoraDate,
|
|
|
|
|
|
|
|
connected_lora_time: connectedLoraTime,
|
|
|
|
|
|
|
|
lora_last_check_time: loraLastCheckTime,
|
|
|
|
|
|
|
|
lora_last_disconnect_time: loraLastDisconnect,
|
|
|
|
|
|
|
|
type: slave.type || "slave",
|
|
|
|
|
|
|
|
typeOfWater,
|
|
|
|
|
|
|
|
connected_to: slave.connected_to || null
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.push({
|
|
|
|
|
|
|
|
hardwareId: master.hardwareId,
|
|
|
|
|
|
|
|
masterName,
|
|
|
|
|
|
|
|
location,
|
|
|
|
|
|
|
|
type: master.type || "master",
|
|
|
|
|
|
|
|
connected_status: gsmStatus,
|
|
|
|
|
|
|
|
connected_slave_count: connectedSlaves.length,
|
|
|
|
|
|
|
|
connected_slaves: connectedSlaves,
|
|
|
|
|
|
|
|
connected_gsm_date: connectedGsmDate,
|
|
|
|
|
|
|
|
connected_gsm_time: connectedGsmTime,
|
|
|
|
|
|
|
|
gsm_last_check_time: gsmLastCheckTime,
|
|
|
|
|
|
|
|
gsm_last_disconnect_time: gsmLastDisconnect,
|
|
|
|
|
|
|
|
connected_lora_date: master.connected_lora_date || null,
|
|
|
|
|
|
|
|
connected_lora_time: master.connected_lora_time || null
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
|
|
|
status_code: 200,
|
|
|
|
|
|
|
|
message: "Master-slave summary retrieved successfully",
|
|
|
|
|
|
|
|
data: result
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error("Error in getMasterSlaveSummary:", error);
|
|
|
|
|
|
|
|
return reply.status(500).send({ error: "Internal Server Error" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|