diff --git a/src/controllers/installationController.js b/src/controllers/installationController.js index 71358a8f..426b570c 100644 --- a/src/controllers/installationController.js +++ b/src/controllers/installationController.js @@ -1366,6 +1366,98 @@ exports.mastrerList = async (req, reply) => { // }; +// exports.getMasterSlaveSummary = async (req, reply) => { +// try { +// const { customerId } = req.params; + +// if (!customerId) { +// return reply.status(400).send({ error: 'customerId is required' }); +// } + +// // Fetch all devices for the customer +// const allDevices = await Insensors.find({ customerId }).lean(); + +// // Group devices +// const masters = allDevices.filter(dev => dev.type === 'master'); +// const slaves = allDevices.filter(dev => dev.type === 'slave'); + +// // Create a map of slaves by connected_to hardwareId +// const slaveMap = {}; +// for (const slave of slaves) { +// const masterId = slave.connected_to; +// if (!slaveMap[masterId]) { +// slaveMap[masterId] = []; +// } + +// const loraTime = slave.connected_lora_time || null; +// const loraDate = slave.connected_lora_date || null; + +// // Fetch masterName using the connected_to masterId +// const master = masters.find(m => m.hardwareId === masterId); +// const masterName = master ? master.masterName : 'Unknown'; + +// slaveMap[masterId].push({ +// hardwareId: slave.hardwareId, +// tankName: slave.tankName || null, +// location: slave.tankLocation || null, +// connected_status: slave.connected_status || 'disconnected', +// connected_lora_time: loraTime, +// connected_lora_date: loraDate, +// type: slave.type || 'N/A', // Add 'type' field +// typeOfWater: slave.typeOfWater || 'N/A', // Add 'typeOfWater' field +// lora_last_check_time: slave.lora_last_check_time && slave.lora_last_check_time +// ? `${slave.lora_last_check_time}` +// : null, // Add 'lora_last_check_time' field +// connected_to: slave.connected_to, // Add 'connected_to' field +// masterName: masterName // Add 'masterName' field +// }); +// } + +// const response = []; + +// for (const master of masters) { +// // Fetch latest IoT data for this master +// const latestData = await IotData.findOne({ hardwareId: master.hardwareId }) +// .sort({ date: -1 }) +// .lean(); + +// const enriched = { +// ...master, +// connected_status: master.connected_status || 'disconnected', +// connected_slave_count: slaveMap[master.hardwareId]?.length || 0, +// connected_slaves: slaveMap[master.hardwareId] || [] +// }; + +// // Use saved GSM fields from Insensors +// if (master.gsm_last_check_time) { +// enriched.gsm_last_check_time = master.gsm_last_check_time; + +// const indiaTime = moment.tz(master.gsm_last_check_time, 'Asia/Kolkata'); +// enriched.connected_gsm_date = indiaTime.format('DD-MM-YYYY'); +// enriched.connected_gsm_time = indiaTime.format('HH:mm:ss'); +// } + +// // If LoRa timestamps are available from master (some masters act like slaves too) +// if (master.connected_lora_date && master.connected_lora_time) { +// enriched.connected_lora_date = master.connected_lora_date; +// enriched.connected_lora_time = master.connected_lora_time; +// } + +// response.push(enriched); +// } + +// return reply.send({ +// status_code: 200, +// message: 'Master-slave summary retrieved successfully', +// data: response +// }); +// } catch (err) { +// console.error('Error in getMasterSlaveSummary:', err); +// return reply.status(500).send({ error: 'Internal Server Error' }); +// } +// }; + + exports.getMasterSlaveSummary = async (req, reply) => { try { const { customerId } = req.params; @@ -1374,15 +1466,13 @@ exports.getMasterSlaveSummary = async (req, reply) => { return reply.status(400).send({ error: 'customerId is required' }); } - // Fetch all devices for the customer const allDevices = await Insensors.find({ customerId }).lean(); - // Group devices const masters = allDevices.filter(dev => dev.type === 'master'); const slaves = allDevices.filter(dev => dev.type === 'slave'); - // Create a map of slaves by connected_to hardwareId const slaveMap = {}; + for (const slave of slaves) { const masterId = slave.connected_to; if (!slaveMap[masterId]) { @@ -1392,9 +1482,22 @@ exports.getMasterSlaveSummary = async (req, reply) => { const loraTime = slave.connected_lora_time || null; const loraDate = slave.connected_lora_date || null; - // Fetch masterName using the connected_to masterId - const master = masters.find(m => m.hardwareId === masterId); - const masterName = master ? master.masterName : 'Unknown'; + const master = masters.find(m => m.hardwareId === masterId); + const masterName = master ? master.masterName : 'Unknown'; + + // If disconnected, update LoRa last disconnect time + let loraLastDisconnect = slave.lora_last_disconnect_time || null; + if (slave.connected_status === 'disconnected') { + const now = moment().tz('Asia/Kolkata').format('YYYY-MM-DD HH:mm:ss'); + await Insensors.updateOne( + { hardwareId: slave.hardwareId }, + { $set: { lora_last_disconnect_time: now } } + ); + loraLastDisconnect = now; + } + + // Get tankHeight from IotData + const tankHeight = await getTankHeight(slave.hardwareId); slaveMap[masterId].push({ hardwareId: slave.hardwareId, @@ -1403,41 +1506,50 @@ exports.getMasterSlaveSummary = async (req, reply) => { connected_status: slave.connected_status || 'disconnected', connected_lora_time: loraTime, connected_lora_date: loraDate, - type: slave.type || 'N/A', // Add 'type' field - typeOfWater: slave.typeOfWater || 'N/A', // Add 'typeOfWater' field - lora_last_check_time: slave.lora_last_check_time && slave.lora_last_check_time - ? `${slave.lora_last_check_time}` - : null, // Add 'lora_last_check_time' field - connected_to: slave.connected_to, // Add 'connected_to' field - masterName: masterName // Add 'masterName' field + lora_last_check_time: slave.lora_last_check_time || null, + lora_last_disconnect_time: loraLastDisconnect, + connected_to: slave.connected_to, + masterName: masterName, + type: slave.type || 'N/A', + typeOfWater: slave.typeOfWater || 'N/A', + tankHeight: tankHeight || null }); } const response = []; for (const master of masters) { - // Fetch latest IoT data for this master - const latestData = await IotData.findOne({ hardwareId: master.hardwareId }) - .sort({ date: -1 }) - .lean(); + const connectedSlaves = slaveMap[master.hardwareId] || []; + + // If disconnected, update GSM last disconnect time + let gsmLastDisconnect = master.gsm_last_disconnect_time || null; + if (master.connected_status === 'disconnected') { + const now = moment().tz('Asia/Kolkata').format('YYYY-MM-DD HH:mm:ss'); + await Insensors.updateOne( + { hardwareId: master.hardwareId }, + { $set: { gsm_last_disconnect_time: now } } + ); + gsmLastDisconnect = now; + } const enriched = { - ...master, + hardwareId: master.hardwareId, + masterName: master.masterName || null, + location: master.location || null, + type: master.type || 'master', connected_status: master.connected_status || 'disconnected', - connected_slave_count: slaveMap[master.hardwareId]?.length || 0, - connected_slaves: slaveMap[master.hardwareId] || [] + connected_slave_count: connectedSlaves.length, + connected_slaves: connectedSlaves, + gsm_last_check_time: master.gsm_last_check_time || null, + gsm_last_disconnect_time: gsmLastDisconnect || null }; - // Use saved GSM fields from Insensors if (master.gsm_last_check_time) { - enriched.gsm_last_check_time = master.gsm_last_check_time; - const indiaTime = moment.tz(master.gsm_last_check_time, 'Asia/Kolkata'); enriched.connected_gsm_date = indiaTime.format('DD-MM-YYYY'); enriched.connected_gsm_time = indiaTime.format('HH:mm:ss'); } - // If LoRa timestamps are available from master (some masters act like slaves too) if (master.connected_lora_date && master.connected_lora_time) { enriched.connected_lora_date = master.connected_lora_date; enriched.connected_lora_time = master.connected_lora_time; @@ -1457,6 +1569,18 @@ exports.getMasterSlaveSummary = async (req, reply) => { } }; +// 🔍 Helper to get tankHeight from latest IotData record +async function getTankHeight(hardwareId) { + const iotData = await IotData.findOne({ 'tanks.tankhardwareId': hardwareId }) + .sort({ date: -1 }) + .lean(); + + if (!iotData) return null; + + const matchedTank = iotData.tanks.find(t => t.tankhardwareId === hardwareId); + return matchedTank?.tankHeight || null; +} + // exports.getIotDataByCustomer = async (req, reply) => { // try { diff --git a/src/models/store.js b/src/models/store.js index 2c9825e4..3c042c36 100644 --- a/src/models/store.js +++ b/src/models/store.js @@ -371,6 +371,8 @@ connected_lora_time: { type: String, default: null }, typeOfWater:{ type: String, default: null }, gsm_last_check_time : { type: String, default: null }, lora_last_check_time : { type: String, default: null }, +gsm_last_disconnect_time : { type: String, default: null }, +lora_last_disconnect_time : { type: String, default: null }, quality_check_details: [{ damage_check: { result: String }, stickering_check: { result: String },