【类 型】:feat
【原 因】:飞行数据传到服务器 【过 程】:订阅飞机状态时候 检测到解锁 就记录飞行数据 切换到加锁之后 将数据长传 数据包括 加解锁时间戳 使用电量 经纬高 飞行距离 【影 响】: # 类型 包含: # feat:新功能(feature) # fix:修补bug # docs:文档(documentation) # style: 格式(不影响代码运行的变动) # refactor:重构(即不是新增功能,也不是修改bug的代码变动) # test:增加测试 # chore:构建过程或辅助工具的变动
This commit is contained in:
parent
c97c8e6d8a
commit
607ab15cf9
@ -18,6 +18,7 @@
|
|||||||
"mqtt": "^2.18.9",
|
"mqtt": "^2.18.9",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
"geodist": "^0.2.1",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-router": "^3.6.5",
|
"vue-router": "^3.6.5",
|
||||||
"vue-template-compiler": "^2.7.16",
|
"vue-template-compiler": "^2.7.16",
|
||||||
@ -38,7 +39,6 @@
|
|||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
"eslint-plugin-standard": "^4.0.0",
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"geodist": "^0.2.1",
|
|
||||||
"sass": "^1.64.1",
|
"sass": "^1.64.1",
|
||||||
"sass-loader": "^8.0.2"
|
"sass-loader": "^8.0.2"
|
||||||
},
|
},
|
||||||
@ -46,4 +46,4 @@
|
|||||||
"main": ".eslintrc.js",
|
"main": ".eslintrc.js",
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
}
|
}
|
@ -304,7 +304,13 @@ const store = new Vuex.Store({
|
|||||||
res.data.airList.forEach(plane => {
|
res.data.airList.forEach(plane => {
|
||||||
plane.planeState = { // 飞机状态初始化字段
|
plane.planeState = { // 飞机状态初始化字段
|
||||||
flyDataMark: false, // 飞机解锁标记成真
|
flyDataMark: false, // 飞机解锁标记成真
|
||||||
flyDataSave: [], // 飞机加锁截至 待上传飞行数据之后 再清空此值
|
flyDataSave: { // 飞机加锁截至 待上传飞行数据之后 再清空此值
|
||||||
|
startTime: null, // 解锁时的时间戳(秒)
|
||||||
|
endTime: null, // 加锁时的时间戳(秒)
|
||||||
|
startBattery: null, // 解锁时的电池电量(百分比)
|
||||||
|
endBattery: null, // 加锁时的电池电量(百分比)
|
||||||
|
path: [] // 飞行路径数组,每项是 [lon, lat, alt]
|
||||||
|
},
|
||||||
heartBeat: null, // 心跳
|
heartBeat: null, // 心跳
|
||||||
heartRandom: null, // 每次接收到心跳创建一个随机数 用于watch监听
|
heartRandom: null, // 每次接收到心跳创建一个随机数 用于watch监听
|
||||||
voltagBattery: null, // 电压信息
|
voltagBattery: null, // 电压信息
|
||||||
|
@ -179,8 +179,14 @@ export async function getFlyData (idArr, startTime, endTime) {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*@abstract 上传保存飞机 飞行数据 检测心跳 解锁开始记录数据 加锁上传数据
|
* @abstract 上传保存飞机飞行数据(解锁至加锁 即飞行结束触发)
|
||||||
|
* @param {Object} data 包含 id, start_time, end_time, gps_path, distance, power_used
|
||||||
*/
|
*/
|
||||||
export async function saveFlyData () {
|
export async function saveFlyData (data) {
|
||||||
|
const params = new URLSearchParams()
|
||||||
|
for (const key in data) {
|
||||||
|
params.append(key, data[key])
|
||||||
|
}
|
||||||
|
const res = await api.post('saveFlyData', params, 'Plane')
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import mqtt from '@/utils/mqtt'
|
import mqtt from '@/utils/mqtt'
|
||||||
|
import geodist from 'geodist'
|
||||||
|
import { saveFlyData } from '@/utils/api/table'
|
||||||
import Menubar from '@/views/layout/components/menubar'
|
import Menubar from '@/views/layout/components/menubar'
|
||||||
import Headbar from '@/views/layout/components/headbar'
|
import Headbar from '@/views/layout/components/headbar'
|
||||||
import BlogBox from '@/views/layout/components/BlogBox'
|
import BlogBox from '@/views/layout/components/BlogBox'
|
||||||
@ -31,6 +33,50 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 加锁时 解构 并 上传飞行数据
|
||||||
|
async handleFlightDataUpload (plane) {
|
||||||
|
const flyData = { ...plane.planeState.flyDataSave }
|
||||||
|
const path = flyData.path || []
|
||||||
|
const distanceList = []
|
||||||
|
|
||||||
|
// 记录加锁时间与电量
|
||||||
|
flyData.endTime = Math.floor(Date.now() / 1000)
|
||||||
|
flyData.endBattery = plane.planeState.batteryRemaining
|
||||||
|
|
||||||
|
// 计算累计飞行距离
|
||||||
|
let totalDistance = 0
|
||||||
|
for (let i = 1; i < path.length; i++) {
|
||||||
|
const prev = path[i - 1]
|
||||||
|
const curr = path[i]
|
||||||
|
const dist = geodist(
|
||||||
|
{ lat: prev[1], lon: prev[0] },
|
||||||
|
{ lat: curr[1], lon: curr[0] },
|
||||||
|
{ exact: true, unit: 'meters' }
|
||||||
|
)
|
||||||
|
totalDistance += dist
|
||||||
|
distanceList.push(dist)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算电量消耗
|
||||||
|
const batteryDrop = (flyData.startBattery || 0) - (flyData.endBattery || 0)
|
||||||
|
const totalCapacity = plane.planeState.battCapacity || 1
|
||||||
|
const powerUsed = Math.round((batteryDrop / 100) * totalCapacity)
|
||||||
|
|
||||||
|
// 构造上传数据
|
||||||
|
const uploadData = {
|
||||||
|
plane_id: plane.id,
|
||||||
|
start_time: flyData.startTime,
|
||||||
|
end_time: flyData.endTime,
|
||||||
|
gps_path: JSON.stringify(path),
|
||||||
|
distance: Math.round(totalDistance),
|
||||||
|
power_used: powerUsed
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await saveFlyData(uploadData)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('上传飞行数据失败', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Menubar,
|
Menubar,
|
||||||
@ -82,7 +128,7 @@ export default {
|
|||||||
// 订阅飞机信息
|
// 订阅飞机信息
|
||||||
mqtt.doSubscribe('planeState/+', (mqttRes) => {
|
mqtt.doSubscribe('planeState/+', (mqttRes) => {
|
||||||
res.forEach(plane => {
|
res.forEach(plane => {
|
||||||
if (mqttRes.topic.indexOf(plane.macadd) > -1) {
|
if (plane.macadd && mqttRes.topic.indexOf(plane.macadd) > -1) {
|
||||||
try {
|
try {
|
||||||
// 反序列化 mqtt信息
|
// 反序列化 mqtt信息
|
||||||
const jsonData = JSON.parse(mqttRes.msg.trim())
|
const jsonData = JSON.parse(mqttRes.msg.trim())
|
||||||
@ -90,28 +136,38 @@ export default {
|
|||||||
// 更新mqtt信息 选择性更新状态
|
// 更新mqtt信息 选择性更新状态
|
||||||
for (const key in jsonData) {
|
for (const key in jsonData) {
|
||||||
if (key === 'heartBeat') {
|
if (key === 'heartBeat') {
|
||||||
const oldMark = plane.planeState.flyDataMark
|
console.log('接收到心跳信息', plane)
|
||||||
const newMark = (Number(jsonData.heartBeat) & 128) !== 0
|
|
||||||
|
|
||||||
// 每次接收到心跳时,更新随机数以触发 watch 监听
|
// 每次接收到心跳时,更新随机数以触发 watch 监听
|
||||||
plane.planeState.heartRandom = Math.random()
|
plane.planeState.heartRandom = Math.random()
|
||||||
plane.planeState.heartBeat = jsonData.heartBeat
|
plane.planeState.heartBeat = jsonData.heartBeat
|
||||||
|
|
||||||
|
const oldMark = plane.planeState.flyDataMark
|
||||||
|
const newMark = (Number(jsonData.heartBeat) & 128) !== 0
|
||||||
|
|
||||||
// 解锁状态变更检测:用于控制飞行数据的采集与上传
|
// 解锁状态变更检测:用于控制飞行数据的采集与上传
|
||||||
if (!oldMark && newMark) {
|
if (!oldMark && newMark) {
|
||||||
// 从加锁切换为解锁:开始记录飞行轨迹
|
// 从加锁切换为解锁:初始化飞行数据记录
|
||||||
plane.planeState.flyDataMark = true
|
plane.planeState.flyDataMark = true
|
||||||
|
plane.planeState.flyDataSave = {
|
||||||
|
startTime: Math.floor(Date.now() / 1000), // 解锁时间(秒)
|
||||||
|
startBattery: plane.planeState.batteryRemaining,
|
||||||
|
endTime: null,
|
||||||
|
endBattery: null,
|
||||||
|
path: []
|
||||||
|
}
|
||||||
} else if (oldMark && !newMark) {
|
} else if (oldMark && !newMark) {
|
||||||
// 从解锁切换为加锁:停止记录并上传飞行轨迹
|
|
||||||
plane.planeState.flyDataMark = false
|
plane.planeState.flyDataMark = false
|
||||||
|
|
||||||
const uploadData = [...plane.planeState.flyDataSave]
|
this.handleFlightDataUpload(plane) // 上传飞行数据
|
||||||
console.log(`上传飞机 ${plane.macadd} 的飞行数据:`, uploadData)
|
|
||||||
// TODO: 后续实现:上传飞行数据接口
|
|
||||||
// await api.post('uploadFlightPath', { macadd: plane.macadd, data: uploadData })
|
|
||||||
|
|
||||||
// 上传完成后清空记录缓存
|
// 上传完成后清空记录缓存
|
||||||
plane.planeState.flyDataSave = []
|
plane.planeState.flyDataSave = {
|
||||||
|
startTime: null, // 解锁时的时间戳(秒)
|
||||||
|
endTime: null, // 加锁时的时间戳(秒)
|
||||||
|
startBattery: null, // 解锁时的电池电量(百分比)
|
||||||
|
endBattery: null, // 加锁时的电池电量(百分比)
|
||||||
|
path: []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (key === 'position') {
|
} else if (key === 'position') {
|
||||||
// 如果是飞机位置信息 则不是直接刷新状态 而是累计 到数组 以便于画出飞机路径
|
// 如果是飞机位置信息 则不是直接刷新状态 而是累计 到数组 以便于画出飞机路径
|
||||||
@ -126,8 +182,12 @@ export default {
|
|||||||
plane.planeState.position.shift() // 删除最早的经纬度
|
plane.planeState.position.shift() // 删除最早的经纬度
|
||||||
}
|
}
|
||||||
// 如果是解锁状态,记录轨迹用于上传
|
// 如果是解锁状态,记录轨迹用于上传
|
||||||
if (plane.planeState.flyDataMark) {
|
if (plane.planeState.flyDataMark && plane.planeState.flyDataSave?.path) {
|
||||||
plane.planeState.flyDataSave.push([position.lon / 10e6, position.lat / 10e6, Number(position.alt)])
|
plane.planeState.flyDataSave.path.push([
|
||||||
|
position.lon / 10e6,
|
||||||
|
position.lat / 10e6,
|
||||||
|
Number(position.alt)
|
||||||
|
])
|
||||||
}
|
}
|
||||||
} else if (key === 'homePosition') {
|
} else if (key === 'homePosition') {
|
||||||
const homePosition = JSON.parse(jsonData.homePosition)// home点反序列化再赋值
|
const homePosition = JSON.parse(jsonData.homePosition)// home点反序列化再赋值
|
||||||
|
Loading…
Reference in New Issue
Block a user