diff --git a/src/controllers/installationController.js b/src/controllers/installationController.js index 67e829b5..5731de98 100644 --- a/src/controllers/installationController.js +++ b/src/controllers/installationController.js @@ -1035,116 +1035,302 @@ exports.mastrerList = async (req, reply) => { // } + + +// exports.getMasterSlaveSummary = async (req, reply) => { +// try { +// const { customerId } = req.params; + +// if (!customerId) { +// return reply.status(400).send({ message: "Missing customerId" }); +// } + +// const allDevices = await Insensors.find({ customerId }); + +// const masters = allDevices.filter(device => device.type === 'master'); +// const slaves = allDevices.filter(device => device.type === 'slave'); + +// const enrichDeviceWithTimestamp = async (device) => { +// const hardwareId = device.hardwareId?.trim(); +// if (!hardwareId) return device.toObject(); + +// const latestData = await IotData.findOne({ hardwareId }).sort({ date: -1 }).lean(); +// const enriched = device.toObject(); + +// if (latestData?.date) { +// const indiaTime = moment.tz(latestData.date, "Asia/Kolkata"); +// const date = indiaTime.format("DD-MM-YYYY"); +// const time = indiaTime.format("HH:mm:ss"); +// const now = moment.tz("Asia/Kolkata"); +// const diffInMinutes = now.diff(indiaTime, "minutes"); +// const isGSMConnected = diffInMinutes <= 1; +// const gsmStatus = isGSMConnected ? "connected" : "disconnected"; + +// if (device.type === 'master') { +// enriched.connected_gsm_date = date; +// enriched.connected_gsm_time = time; +// enriched.gsm_connected_status = gsmStatus; +// enriched.gsm_last_check_time = indiaTime.format("YYYY-MM-DD HH:mm:ss"); +// } +// } + +// if (latestData?.tanks && Array.isArray(latestData.tanks)) { +// const enrichedTanks = latestData.tanks.map(tank => { +// const tankMoment = moment.tz(tank.date, "Asia/Kolkata"); +// const tankDiff = moment.tz("Asia/Kolkata").diff(tankMoment, "minutes"); +// const loraStatus = tankDiff <= 1 ? "connected" : "disconnected"; +// return { +// ...tank, +// connected_status: loraStatus +// }; +// }); + +// enriched.tanks = enrichedTanks; + +// if (device.type === 'slave') { +// const connectedTank = enrichedTanks.find(tank => tank.tankhardwareId === device.hardwareId); +// enriched.lora_connected_status = connectedTank ? connectedTank.connected_status : "disconnected"; +// enriched.connected_lora_date = connectedTank ? moment(connectedTank.date).tz("Asia/Kolkata").format("DD-MM-YYYY") : null; +// enriched.connected_lora_time = connectedTank ? connectedTank.time : null; +// enriched.lora_last_check_time = connectedTank ? moment(connectedTank.date).tz("Asia/Kolkata").format("YYYY-MM-DD HH:mm:ss") : null; +// } +// } + +// if (device.type === 'slave') { +// delete enriched.connected_gsm_date; +// delete enriched.connected_gsm_time; +// delete enriched.gsm_connected_status; +// delete enriched.gsm_last_check_time; +// } + +// if (device.type === 'master') { +// delete enriched.connected_lora_date; +// delete enriched.connected_lora_time; +// delete enriched.lora_connected_status; +// delete enriched.lora_last_check_time; +// delete enriched.tanks; // ✅ Remove tanks for master +// } + +// return enriched; +// }; + +// const enrichedMasters = await Promise.all(masters.map(enrichDeviceWithTimestamp)); +// const enrichedSlaves = await Promise.all(slaves.map(enrichDeviceWithTimestamp)); + +// const masterSummary = enrichedMasters.map(master => { +// const connectedSlaves = enrichedSlaves.filter(slave => slave.connected_to === master.connected_to); +// return { +// ...master, +// connected_slave_count: connectedSlaves.length, +// connected_slaves: connectedSlaves +// }; +// }); + +// return reply.send({ +// status_code: 200, +// message: "Success", +// master_count: enrichedMasters.length, +// slave_count: enrichedSlaves.length, +// data: masterSummary +// }); + +// } catch (err) { +// console.error("Error in getMasterSlaveSummary:", err); +// return reply.status(500).send({ +// status_code: 500, +// message: "Internal Server Error" +// }); +// } +// }; + + + + +// exports.getMasterSlaveSummary = async (req, reply) => { +// try { +// const { customerId } = req.params; + +// if (!customerId) { +// return reply.status(400).send({ message: "Missing customerId" }); +// } + +// const allDevices = await Insensors.find({ customerId }); +// const masters = allDevices.filter(d => d.type === 'master'); +// const slaves = allDevices.filter(d => d.type === 'slave'); + +// const enrichDevice = async (device) => { +// const enriched = device.toObject(); +// const hardwareId = device.hardwareId?.trim(); + +// if (!hardwareId) return enriched; + +// // Fetch latest IotData blindly for this device +// const latestData = await IotData.findOne({ hardwareId }).sort({ date: -1 }).lean(); + +// if (latestData?.date) { +// const indiaTime = moment.tz(latestData.date, "Asia/Kolkata"); +// const now = moment.tz("Asia/Kolkata"); +// const diffMins = now.diff(indiaTime, "minutes"); +// const isConnected = diffMins <= 1; + +// enriched.connected_gsm_date = indiaTime.format("DD-MM-YYYY"); +// enriched.connected_gsm_time = indiaTime.format("HH:mm:ss"); +// enriched.gsm_connected_status = isConnected ? "connected" : "disconnected"; +// enriched.gsm_last_check_time = indiaTime.format("YYYY-MM-DD HH:mm:ss"); +// } + +// // Only apply LoRa logic for slaves +// if (device.type === 'slave' && latestData?.tanks?.length) { +// const matchingTank = latestData.tanks.find( +// tank => tank.tankhardwareId?.trim() === hardwareId +// ); + +// if (matchingTank) { +// const loraTime = moment.tz(matchingTank.date, "Asia/Kolkata"); +// const loraDiff = moment.tz("Asia/Kolkata").diff(loraTime, "minutes"); +// const isLoraConnected = loraDiff <= 1; + +// enriched.connected_lora_date = loraTime.format("DD-MM-YYYY"); +// enriched.connected_lora_time = matchingTank.time; +// enriched.lora_connected_status = isLoraConnected ? "connected" : "disconnected"; +// enriched.lora_last_check_time = loraTime.format("YYYY-MM-DD HH:mm:ss"); +// } else { +// enriched.connected_lora_date = null; +// enriched.connected_lora_time = null; +// enriched.lora_connected_status = "disconnected"; +// enriched.lora_last_check_time = null; +// } +// } + +// // Remove irrelevant fields +// if (device.type === 'slave') { +// delete enriched.tanks; +// } +// if (device.type === 'master') { +// delete enriched.connected_lora_date; +// delete enriched.connected_lora_time; +// delete enriched.lora_connected_status; +// delete enriched.lora_last_check_time; +// delete enriched.tanks; +// } + +// return enriched; +// }; + +// const enrichedMasters = await Promise.all(masters.map(enrichDevice)); +// const enrichedSlaves = await Promise.all(slaves.map(enrichDevice)); + +// const masterSummary = enrichedMasters.map(master => { +// const connectedSlaves = enrichedSlaves.filter( +// slave => slave.connected_to === master.connected_to +// ); +// return { +// ...master, +// connected_slave_count: connectedSlaves.length, +// connected_slaves: connectedSlaves +// }; +// }); + +// return reply.send({ +// status_code: 200, +// message: "Success", +// master_count: enrichedMasters.length, +// slave_count: enrichedSlaves.length, +// data: masterSummary +// }); + +// } catch (err) { +// console.error("Error in getMasterSlaveSummary:", err); +// return reply.status(500).send({ +// status_code: 500, +// message: "Internal Server Error" +// }); +// } +// }; + exports.getMasterSlaveSummary = async (req, reply) => { try { const { customerId } = req.params; if (!customerId) { - return reply.status(400).send({ message: "Missing customerId" }); + return reply.status(400).send({ error: 'customerId is required' }); } - const allDevices = await Insensors.find({ customerId }); + // Fetch all devices for the customer + const allDevices = await Insensors.find({ customerId }).lean(); - const masters = allDevices.filter(device => device.type === 'master'); - const slaves = allDevices.filter(device => device.type === 'slave'); + // Group devices + const masters = allDevices.filter(dev => dev.type === 'master'); + const slaves = allDevices.filter(dev => dev.type === 'slave'); - const enrichDeviceWithTimestamp = async (device) => { - const hardwareId = device.hardwareId?.trim(); - if (!hardwareId) return device.toObject(); + // 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 latestData = await IotData.findOne({ hardwareId }).sort({ date: -1 }).lean(); - const enriched = device.toObject(); + const loraTime = slave.connected_lora_time || null; + const loraDate = slave.connected_lora_date || null; - if (latestData?.date) { - const indiaTime = moment.tz(latestData.date, "Asia/Kolkata"); - const date = indiaTime.format("DD-MM-YYYY"); - const time = indiaTime.format("HH:mm:ss"); - const now = moment.tz("Asia/Kolkata"); - const diffInMinutes = now.diff(indiaTime, "minutes"); - const isGSMConnected = diffInMinutes <= 1; - const gsmStatus = isGSMConnected ? "connected" : "disconnected"; + 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 + }); + } - if (device.type === 'master') { - enriched.connected_gsm_date = date; - enriched.connected_gsm_time = time; - enriched.gsm_connected_status = gsmStatus; - enriched.gsm_last_check_time = indiaTime.format("YYYY-MM-DD HH:mm:ss"); - } - } + const response = []; - if (latestData?.tanks && Array.isArray(latestData.tanks)) { - const enrichedTanks = latestData.tanks.map(tank => { - const tankMoment = moment.tz(tank.date, "Asia/Kolkata"); - const tankDiff = moment.tz("Asia/Kolkata").diff(tankMoment, "minutes"); - const loraStatus = tankDiff <= 1 ? "connected" : "disconnected"; - return { - ...tank, - connected_status: loraStatus - }; - }); + for (const master of masters) { + // Fetch latest IoT data for this master + const latestData = await IotData.findOne({ hardwareId: master.hardwareId }) + .sort({ date: -1 }) + .lean(); - enriched.tanks = enrichedTanks; + const enriched = { + ...master, + connected_status: master.connected_status || 'disconnected', + connected_slave_count: slaveMap[master.hardwareId]?.length || 0, + connected_slaves: slaveMap[master.hardwareId] || [] + }; - if (device.type === 'slave') { - const connectedTank = enrichedTanks.find(tank => tank.tankhardwareId === device.hardwareId); - enriched.lora_connected_status = connectedTank ? connectedTank.connected_status : "disconnected"; - enriched.connected_lora_date = connectedTank ? moment(connectedTank.date).tz("Asia/Kolkata").format("DD-MM-YYYY") : null; - enriched.connected_lora_time = connectedTank ? connectedTank.time : null; - enriched.lora_last_check_time = connectedTank ? moment(connectedTank.date).tz("Asia/Kolkata").format("YYYY-MM-DD HH:mm:ss") : null; - } - } + // Use saved GSM fields from Insensors + if (master.gsm_last_check_time) { + enriched.gsm_last_check_time = master.gsm_last_check_time; - if (device.type === 'slave') { - delete enriched.connected_gsm_date; - delete enriched.connected_gsm_time; - delete enriched.gsm_connected_status; - delete enriched.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 (device.type === 'master') { - delete enriched.connected_lora_date; - delete enriched.connected_lora_time; - delete enriched.lora_connected_status; - delete enriched.lora_last_check_time; - delete enriched.tanks; // ✅ Remove tanks for master + // 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; } - return enriched; - }; - - const enrichedMasters = await Promise.all(masters.map(enrichDeviceWithTimestamp)); - const enrichedSlaves = await Promise.all(slaves.map(enrichDeviceWithTimestamp)); - - const masterSummary = enrichedMasters.map(master => { - const connectedSlaves = enrichedSlaves.filter(slave => slave.connected_to === master.connected_to); - return { - ...master, - connected_slave_count: connectedSlaves.length, - connected_slaves: connectedSlaves - }; - }); + response.push(enriched); + } return reply.send({ status_code: 200, - message: "Success", - master_count: enrichedMasters.length, - slave_count: enrichedSlaves.length, - data: masterSummary + message: 'Master-slave summary retrieved successfully', + data: response }); - } catch (err) { - console.error("Error in getMasterSlaveSummary:", err); - return reply.status(500).send({ - status_code: 500, - message: "Internal Server Error" - }); + console.error('Error in getMasterSlaveSummary:', err); + return reply.status(500).send({ error: 'Internal Server Error' }); } }; - // exports.getIotDataByCustomer = async (req, reply) => { // try { // const { customerId } = req.params;