|
@@ -78,7 +78,7 @@
|
|
v-if="furnitureItems && furnitureItems.some((item) => item.type === 'bed')"
|
|
v-if="furnitureItems && furnitureItems.some((item) => item.type === 'bed')"
|
|
class="breathLine"
|
|
class="breathLine"
|
|
>
|
|
>
|
|
- <BreathLineChart></BreathLineChart>
|
|
|
|
|
|
+ <BreathLineChart :data="breathRpmList"></BreathLineChart>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</info-card>
|
|
</info-card>
|
|
@@ -344,10 +344,14 @@ const resetMqttTimeout = () => {
|
|
if (mqttTimeout) clearTimeout(mqttTimeout)
|
|
if (mqttTimeout) clearTimeout(mqttTimeout)
|
|
mqttTimeout = window.setTimeout(() => {
|
|
mqttTimeout = window.setTimeout(() => {
|
|
Object.keys(targets).forEach((key) => delete targets[Number(key)])
|
|
Object.keys(targets).forEach((key) => delete targets[Number(key)])
|
|
|
|
+ breathRpmList.value = []
|
|
console.log('MQTT超时未收到新消息,隐藏所有红点')
|
|
console.log('MQTT超时未收到新消息,隐藏所有红点')
|
|
}, MQTT_TIMEOUT_MS)
|
|
}, MQTT_TIMEOUT_MS)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 呼吸率
|
|
|
|
+const breathRpmList = ref<number[]>([])
|
|
|
|
+
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
console.log('onMounted', mqttClient)
|
|
console.log('onMounted', mqttClient)
|
|
const mqttConfig = {
|
|
const mqttConfig = {
|
|
@@ -361,31 +365,38 @@ onMounted(() => {
|
|
username: mqttConfig.username,
|
|
username: mqttConfig.username,
|
|
password: mqttConfig.password,
|
|
password: mqttConfig.password,
|
|
})
|
|
})
|
|
- console.log('mqttClient connect ready', mqttClient)
|
|
|
|
|
|
+ console.log('⌛️ mqttClient connect ready', mqttClient)
|
|
mqttClient.on('connect', () => {
|
|
mqttClient.on('connect', () => {
|
|
- console.log('MQTT已连接')
|
|
|
|
|
|
+ console.log('✅ MQTT已连接')
|
|
// 订阅所有设备的主题
|
|
// 订阅所有设备的主题
|
|
- mqttClient?.subscribe(`/mps/${clientId.value}/realtime_pos`, (err) => {
|
|
|
|
|
|
+ const sub = `/dev/${clientId.value}/dsp_data`
|
|
|
|
+ mqttClient?.subscribe(sub, (err) => {
|
|
if (err) {
|
|
if (err) {
|
|
- console.error('MQTT订阅失败', err)
|
|
|
|
|
|
+ console.error('❌ MQTT订阅失败', err)
|
|
} else {
|
|
} else {
|
|
- console.log(`已订阅主题 /mps/${clientId.value}/realtime_pos`)
|
|
|
|
|
|
+ console.log(`⚛️ 已订阅主题 ${sub}`)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
})
|
|
})
|
|
mqttClient.on('error', (err) => {
|
|
mqttClient.on('error', (err) => {
|
|
- console.error('MQTT连接错误', err)
|
|
|
|
|
|
+ console.error('❌ MQTT连接错误', err)
|
|
})
|
|
})
|
|
mqttClient.on('message', (topic: string, message: Uint8Array) => {
|
|
mqttClient.on('message', (topic: string, message: Uint8Array) => {
|
|
resetMqttTimeout()
|
|
resetMqttTimeout()
|
|
- const match = topic.match(/^\/mps\/(.+)\/realtime_pos$/)
|
|
|
|
|
|
+ const subMatch = /^\/dev\/(.+)\/dsp_data$/
|
|
|
|
+ const match = topic.match(subMatch)
|
|
if (!match) return
|
|
if (!match) return
|
|
const msgDevId = match[1]
|
|
const msgDevId = match[1]
|
|
if (msgDevId !== clientId.value) return // 只处理当前设备
|
|
if (msgDevId !== clientId.value) return // 只处理当前设备
|
|
try {
|
|
try {
|
|
const data = JSON.parse(message.toString())
|
|
const data = JSON.parse(message.toString())
|
|
- const arr = data.targetPoints
|
|
|
|
- console.log('收到MQTT消息', data, data.targetPoints)
|
|
|
|
|
|
+ const arr = data.tracker_targets
|
|
|
|
+ console.log('🚀 收到MQTT消息', data, {
|
|
|
|
+ '🔴 目标人数': data.tracker_targets.length,
|
|
|
|
+ '🟢 呼吸率': data.health.breath_rpm,
|
|
|
|
+ '🟡 点位图': data.tracker_targets,
|
|
|
|
+ })
|
|
|
|
+ breathRpmList.value.push(Math.floor(data.health.breath_rpm || 0))
|
|
if (Array.isArray(arr) && arr.length > 0 && Array.isArray(arr[0])) {
|
|
if (Array.isArray(arr) && arr.length > 0 && Array.isArray(arr[0])) {
|
|
// 记录本次出现的所有id
|
|
// 记录本次出现的所有id
|
|
const currentIds = new Set<number>()
|
|
const currentIds = new Set<number>()
|
|
@@ -407,7 +418,7 @@ onMounted(() => {
|
|
targets[id].lastY = y
|
|
targets[id].lastY = y
|
|
targets[id].displayX = x
|
|
targets[id].displayX = x
|
|
targets[id].displayY = y
|
|
targets[id].displayY = y
|
|
- console.log(`更新目标点: id=${id}, x=${x}, y=${y}`, targets[id])
|
|
|
|
|
|
+ console.log(`🔄 更新目标点: id=${id}, x=${x}, y=${y}`, targets[id])
|
|
} else {
|
|
} else {
|
|
// 距离太小,忽略本次更新
|
|
// 距离太小,忽略本次更新
|
|
// console.log(`忽略微小抖动 id=${id}`)
|
|
// console.log(`忽略微小抖动 id=${id}`)
|
|
@@ -424,7 +435,7 @@ onMounted(() => {
|
|
} else {
|
|
} else {
|
|
// 没有目标时,隐藏所有红点
|
|
// 没有目标时,隐藏所有红点
|
|
Object.keys(targets).forEach((key) => delete targets[Number(key)])
|
|
Object.keys(targets).forEach((key) => delete targets[Number(key)])
|
|
- // console.log('tracker_targets为空,隐藏所有红点')
|
|
|
|
|
|
+ breathRpmList.value = []
|
|
}
|
|
}
|
|
} catch (e) {
|
|
} catch (e) {
|
|
console.error('MQTT消息解析失败', e)
|
|
console.error('MQTT消息解析失败', e)
|
|
@@ -432,6 +443,10 @@ onMounted(() => {
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+// setInterval(() => {
|
|
|
|
+// breathRpmList.value.push(Math.floor(Math.random() * 30))
|
|
|
|
+// }, 100)
|
|
|
|
+
|
|
const areaAvailable = computed(() => {
|
|
const areaAvailable = computed(() => {
|
|
const { length, width } = detailState.value
|
|
const { length, width } = detailState.value
|
|
return Number(length) < 50 || Number(width) < 50
|
|
return Number(length) < 50 || Number(width) < 50
|