Merge branch 'main' of http://123.132.248.154:10000/gitY/DiKongGanZhiPingTai
commit
9f3bdd049d
|
|
@ -0,0 +1,11 @@
|
|||
import { defHttp } from '@/utils/http/axios';
|
||||
enum Api {
|
||||
GetDataList = '/api/Manage/GetDataList',
|
||||
}
|
||||
|
||||
export function GetDataList(params) {
|
||||
return defHttp.get({
|
||||
url: Api.GetDataList,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
|
@ -1,5 +1,15 @@
|
|||
import { clientReizePublish, clientReizeSubscribe } from '@/utils/mqtt';
|
||||
|
||||
export const return_home_status = {
|
||||
canceled: '取消或终止',
|
||||
failed: '失败',
|
||||
in_progress: '执行中',
|
||||
ok: '执行成功',
|
||||
paused: '暂停',
|
||||
rejected: '拒绝',
|
||||
sent: '已下发',
|
||||
timeout: '超时',
|
||||
};
|
||||
export const eventsTopic = (data) => {
|
||||
// 发送消息
|
||||
clientReizePublish('thing/product/8UUXN5400A079H/events', data);
|
||||
|
|
|
|||
|
|
@ -29,3 +29,12 @@ export const services_replyTopic = () => {
|
|||
// 订阅消息
|
||||
clientSubscribe('thing/product/8UUXN5400A079H/services_reply');
|
||||
};
|
||||
// 无人机
|
||||
export const servicesUAVTopic = (data) => {
|
||||
// 发送消息
|
||||
clientPublish('thing/product/1581F8HGX254V00A0BUY/services', data);
|
||||
};
|
||||
export const services_replyUAVTopic = () => {
|
||||
// 订阅消息
|
||||
clientSubscribe('thing/product/1581F8HGX254V00A0BUY/services_reply');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const connection = {
|
|||
connectTimeout: 30 * 1000, // ms
|
||||
reconnectPeriod: 4000, // ms
|
||||
// clientId: 'mqttx_' + Math.random().toString(16).substring(2, 8),
|
||||
clientId: 'mqtt_client_1581F8HGX254V00A0BUY',
|
||||
clientId: `mqtt_${Math.random().toString(16).slice(2)}`,
|
||||
// auth
|
||||
username: 'sdhc',
|
||||
password: '',
|
||||
|
|
@ -43,11 +43,23 @@ const handleOnReConnect = () => {
|
|||
}
|
||||
};
|
||||
// 创建连接函数
|
||||
const createConnection = () => {
|
||||
const createConnection = (callback?) => {
|
||||
try {
|
||||
const { protocol, host, port, endpoint, ...options } = connection;
|
||||
const connectUrl = `${protocol}://${host}:${port}${endpoint}`;
|
||||
client = mqtt.connect(connectUrl, options);
|
||||
client.on('connect', () => {
|
||||
console.log('✅ 已连接');
|
||||
if(callback){
|
||||
callback()
|
||||
}
|
||||
});
|
||||
client.on('close', () => {
|
||||
console.log('❌ 连接已关闭');
|
||||
});
|
||||
client.on('error', (err) => {
|
||||
console.error('❌ 出错了:', err);
|
||||
});
|
||||
if (client.on) {
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -95,6 +107,14 @@ const clientPublish = (topic: string, querys: any) => {
|
|||
}
|
||||
});
|
||||
};
|
||||
// 获取连接状态
|
||||
const getConnectStatus = () => {
|
||||
console.log('client',client)
|
||||
if (!client.connected) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// on 事件
|
||||
// connect 连接
|
||||
// reconnect 重新连接
|
||||
|
|
@ -162,4 +182,5 @@ export {
|
|||
getReizeClient,
|
||||
clientReizeSubscribe,
|
||||
clientReizePublish,
|
||||
getConnectStatus,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,3 +40,32 @@ export function buildShortUUID(prefix = ''): string {
|
|||
unique++;
|
||||
return prefix + '_' + random + unique + String(time);
|
||||
}
|
||||
export function uuid(len, radix) {
|
||||
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
||||
let uuid = [],
|
||||
i;
|
||||
radix = radix || chars.length;
|
||||
|
||||
if (len) {
|
||||
// Compact form
|
||||
for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
|
||||
} else {
|
||||
// rfc4122, version 4 form
|
||||
let r;
|
||||
|
||||
// rfc4122 requires these characters
|
||||
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
||||
uuid[14] = '4';
|
||||
|
||||
// Fill in random data. At i==19 set the high bits of clock sequence as
|
||||
// per rfc4122, sec. 4.1.5
|
||||
for (i = 0; i < 36; i++) {
|
||||
if (!uuid[i]) {
|
||||
r = 0 | (Math.random() * 16);
|
||||
uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uuid.join('');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,29 @@
|
|||
<template>
|
||||
<BasicTable class="w-4/4 xl:w-5/5" @register="registerTable">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="openFeedbackDrawer">设备定损与反馈</a-button>
|
||||
<a-button type="primary" @click="openDeviceBindingModal">设备绑定码</a-button>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key == 'workSpaceId'">
|
||||
{{ props.projectList.find(item => item.value == record.workSpaceId)?.label }}
|
||||
</template>
|
||||
<template v-if="column.key == 'first_power_on'">
|
||||
{{ record.first_power_on? dayjs(record.first_power_on).format('YYYY-MM-DD HH:mm:ss'): '' }}
|
||||
</template>
|
||||
<template v-if="column.key == 'compatible_status'">
|
||||
{{ record.compatible_status? record.compatible_status == 0? "不需要一致性升级": "需要一致性升级": "" }}
|
||||
</template>
|
||||
<template v-if="column.key == 'flighttask_step_code'">
|
||||
{{ workStatus(record)}}
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
icon: 'ant-design:file-search-outlined',
|
||||
onClick: () => {
|
||||
console.log('deviceInfoList',deviceInfoList)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -26,24 +39,70 @@
|
|||
<a-drawer class="feedback-drawer" v-model:open="feedbackDrawer" width="80%" :closable="false">
|
||||
<FeedbackDrawer />
|
||||
</a-drawer>
|
||||
<a-drawer class="feedback-drawer" v-model:open="feedbackDrawer" width="45%" :closable="false">
|
||||
<FeedbackDrawer />
|
||||
</a-drawer>
|
||||
<a-modal v-model:open="deviceBindingModal" title="设备绑定码" @ok="handleOk">
|
||||
<DeviceBindModal />
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { ref, defineProps, onMounted, watch, nextTick } from "vue"
|
||||
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||
import { columns, dataSource, searchFormSchema } from './utils'
|
||||
import { columns, searchFormSchema } from './utils'
|
||||
import FeedbackDrawer from './FeedbackDrawer/index.vue'
|
||||
import DeviceBindModal from './DeviceBindModal/index.vue'
|
||||
import { GetDataList } from '@/api/demo/device'
|
||||
import { getClient, clientSubscribe } from '@/utils/mqtt'
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const props = defineProps(['projectList','connected'])
|
||||
watch(() => props.projectList, () => {
|
||||
const targetField = searchFormSchema.find(item => item.field === 'project');
|
||||
if (targetField) {
|
||||
targetField.componentProps = {
|
||||
...(targetField.componentProps || {}),
|
||||
options: props.projectList,
|
||||
};
|
||||
}
|
||||
})
|
||||
watch(() => props.connected, () => {
|
||||
getClient().on('message', (topic, message) => {
|
||||
const rs = JSON.parse(message)
|
||||
console.log('rs',rs)
|
||||
console.log('getDataSource',getDataSource())
|
||||
let list = getDataSource()
|
||||
let sn = rs.gateway
|
||||
for(let i = 0; i < list.length; i++){
|
||||
if(list[i].sn == sn){
|
||||
list[i] = {...list[i],...rs.data}
|
||||
}
|
||||
}
|
||||
setTableData(list)
|
||||
});
|
||||
})
|
||||
|
||||
const feedbackDrawer = ref(false)
|
||||
const deviceBindingModal = ref(false)
|
||||
const [registerTable, { reload, expandAll, getForm}] = useTable({
|
||||
const afterFetch = ref(false)
|
||||
const deviceControl = ref(false)
|
||||
watch(() => [afterFetch.value, props.connected], ([newAfterFetch, newConnected], [oldAfterFetch, oldConnected]) => {
|
||||
console.log(newAfterFetch,newConnected)
|
||||
console.log(getDataSource())
|
||||
if(newConnected && newAfterFetch){
|
||||
nextTick(() => {
|
||||
console.log(getDataSource())
|
||||
getDataSource().forEach(item => {
|
||||
let topicUrl = `thing/product/${item.sn}/osd`;
|
||||
clientSubscribe(topicUrl);
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
const [registerTable, { reload, expandAll, getForm,getDataSource,setTableData }] = useTable({
|
||||
title: '机场',
|
||||
// api: (params) => LoadCaseInfoLists(type,params),
|
||||
dataSource,
|
||||
api: GetDataList,
|
||||
columns,
|
||||
rowKey: 'id',
|
||||
formConfig: {
|
||||
|
|
@ -57,16 +116,15 @@ const [registerTable, { reload, expandAll, getForm}] = useTable({
|
|||
useSearchForm: true,
|
||||
// 显示表格设置工具
|
||||
showTableSetting: true,
|
||||
bordered: true,
|
||||
bordered: false,
|
||||
beforeFetch(data) {
|
||||
let params = {...data}
|
||||
if(!params.nowStatus){
|
||||
params.nowStatus = '复提待审核'
|
||||
}
|
||||
return params
|
||||
return data
|
||||
},
|
||||
afterFetch(data) {
|
||||
console.log('afterFetch', data);
|
||||
afterFetch.value = true
|
||||
return data.map(item => {
|
||||
return {...item, children: item.uavList}
|
||||
})
|
||||
},
|
||||
actionColumn: {
|
||||
width: 100,
|
||||
|
|
@ -83,6 +141,30 @@ const openFeedbackDrawer = () => {
|
|||
const openDeviceBindingModal = () => {
|
||||
deviceBindingModal.value = true
|
||||
}
|
||||
const workStatus = (record) => {
|
||||
if(record.flighttask_step_code){
|
||||
switch(record.flighttask_step_code){
|
||||
case 0:
|
||||
return '作业准备中'
|
||||
case 1:
|
||||
return '飞行作业中'
|
||||
case 2:
|
||||
return '作业后状态恢复'
|
||||
case 3:
|
||||
return '自定义飞行区更新中'
|
||||
case 4:
|
||||
return '地形障碍物更新中'
|
||||
case 5:
|
||||
return '任务空闲'
|
||||
case 255:
|
||||
return '飞行器异常'
|
||||
case 256:
|
||||
return '未知状态'
|
||||
}
|
||||
}else{
|
||||
return ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { BasicColumn, FormSchema } from '@/components/Table';
|
|||
export const columns = [
|
||||
{
|
||||
title: '设备型号',
|
||||
dataIndex: 'model',
|
||||
dataIndex: 'typeId',
|
||||
},
|
||||
{
|
||||
title: '设备SN',
|
||||
|
|
@ -18,7 +18,7 @@ export const columns = [
|
|||
},
|
||||
{
|
||||
title: '固件升级',
|
||||
dataIndex: 'upgrade',
|
||||
dataIndex: 'compatible_status',
|
||||
},
|
||||
{
|
||||
title: '飞行安全数据库',
|
||||
|
|
@ -26,11 +26,11 @@ export const columns = [
|
|||
},
|
||||
{
|
||||
title: '工作状态',
|
||||
dataIndex: 'status',
|
||||
dataIndex: 'flighttask_step_code',
|
||||
},
|
||||
{
|
||||
title: '所属项目',
|
||||
dataIndex: 'project',
|
||||
dataIndex: 'workSpaceId',
|
||||
},
|
||||
{
|
||||
title: '加入组织时间',
|
||||
|
|
@ -38,26 +38,10 @@ export const columns = [
|
|||
},
|
||||
{
|
||||
title: '在线时间',
|
||||
dataIndex: 'online_time',
|
||||
dataIndex: 'first_power_on',
|
||||
},
|
||||
];
|
||||
export const dataSource = [
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
{ model: 111, sn:222, name: 333, version: 444, upgrade:'1.0.0', database:'test', status: 555, project: 666, join_time: 777, online_time: 888 },
|
||||
]
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'upgrade_status',
|
||||
|
|
|
|||
|
|
@ -2,20 +2,51 @@
|
|||
<div class="device-page">
|
||||
<a-tabs v-model:activeKey="activeKey" class="device-tabs">
|
||||
<a-tab-pane key="airport" tab="机场">
|
||||
<Airport />
|
||||
<Airport :connected="connected" :projectList="projectList"/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="aerocraft" tab="飞行器">
|
||||
<Aerocraft />
|
||||
<Aerocraft :projectList="projectList"/>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { ref, onMounted, onBeforeUnmount } from "vue"
|
||||
import Airport from './Airport/index.vue'
|
||||
import Aerocraft from './Aerocraft/index.vue'
|
||||
import { GetWorkspaceList } from '@/api/demo/projecthome'
|
||||
import { getConnectStatus,createConnection,destroyConnection } from '@/utils/mqtt'
|
||||
|
||||
onMounted(() => {
|
||||
if(!getConnectStatus()){
|
||||
console.log("需要重连")
|
||||
createConnection(changeConnect)
|
||||
connectMQTT.value = true
|
||||
}else{
|
||||
changeConnect()
|
||||
}
|
||||
GetWorkspaceList().then(res => {
|
||||
projectList.value = res.map(item => {
|
||||
return {
|
||||
label: item.WorkspaceName,
|
||||
value: item.Id,
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
if(connectMQTT.value){
|
||||
destroyConnection()
|
||||
}
|
||||
})
|
||||
const changeConnect = () => {
|
||||
connected.value = true
|
||||
}
|
||||
const activeKey = ref('airport')
|
||||
const projectList = ref([])
|
||||
const connectMQTT = ref(false)
|
||||
const connected = ref(false)
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ export { default as LivePreview } from './src/LivePreview.vue';
|
|||
export { default as RemoteDebugging } from './src/RemoteDebugging.vue';
|
||||
export { default as LoadControl } from './src/LoadControl.vue';
|
||||
export { default as FlightControl } from './src/FlightControl.vue';
|
||||
export { default as TakeOffForm } from './src/TakeOffForm.vue';
|
||||
export { default as Map } from '../workplan/components/map.vue';
|
||||
|
|
|
|||
|
|
@ -24,10 +24,14 @@
|
|||
</div>
|
||||
<!-- 飞行控制 -->
|
||||
<div v-if="flightControlVisible">
|
||||
<FlightControl @changeFlightControl="changeFlightControl" />
|
||||
<FlightControl @changeFlightControl="changeFlightControl" @clickTakeOff="clickTakeOff" />
|
||||
</div>
|
||||
<!-- 一键起飞表单 -->
|
||||
<div v-if="takeOffFormVisible">
|
||||
<TakeOffForm @changeTakeOffForm="changeTakeOffForm" />
|
||||
</div>
|
||||
<div class="AirportLive" v-if="airportLiveVisible" v-drag>
|
||||
<AirportLive />
|
||||
<AirportLive :msgData="msgData" />
|
||||
</div>
|
||||
<div
|
||||
class="LivePreview"
|
||||
|
|
@ -35,7 +39,7 @@
|
|||
:style="{ bottom: airportLiveVisible ? '300px' : '20px' }"
|
||||
v-drag
|
||||
>
|
||||
<LivePreview />
|
||||
<LivePreview :msgData="msgData" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -51,6 +55,7 @@
|
|||
RemoteDebugging,
|
||||
LoadControl,
|
||||
FlightControl,
|
||||
TakeOffForm,
|
||||
} from './index';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
import { getClient, createConnection, clientSubscribe } from '@/utils/mqtt';
|
||||
|
|
@ -81,6 +86,8 @@
|
|||
const loadControlVisible = ref(false);
|
||||
// 飞行控制
|
||||
const flightControlVisible = ref(false);
|
||||
// 一键起飞表单
|
||||
const takeOffFormVisible = ref(false);
|
||||
const changeAirportLive = () => {
|
||||
airportLiveVisible.value = !airportLiveVisible.value;
|
||||
};
|
||||
|
|
@ -93,6 +100,13 @@
|
|||
const changeFlightControl = () => {
|
||||
flightControlVisible.value = !flightControlVisible.value;
|
||||
};
|
||||
const clickTakeOff = () => {
|
||||
console.log('clickTakeOff');
|
||||
takeOffFormVisible.value = true;
|
||||
};
|
||||
const changeTakeOffForm = () => {
|
||||
takeOffFormVisible.value = false;
|
||||
};
|
||||
const msgData = ref();
|
||||
const changeSelect = async (value?: any) => {
|
||||
console.log(value);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
<div class="title">机场直播</div>
|
||||
<div class="title-icon">
|
||||
<RedoOutlined @click="startLiveFun" />
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<ExpandOutlined />
|
||||
<!-- <a-divider type="vertical" style="border-color: #4e5778" /> -->
|
||||
<!-- <ExpandOutlined /> -->
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<PoweroffOutlined @click="closeLive" />
|
||||
</div>
|
||||
|
|
@ -25,44 +25,116 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { RedoOutlined, ExpandOutlined, PoweroffOutlined } from '@ant-design/icons-vue';
|
||||
import { onMounted, onBeforeUnmount } from 'vue';
|
||||
import { onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import { startLive, endLive } from '@/api/workmanagement/airportMaintenance';
|
||||
import TCPlayer from 'tcplayer.js';
|
||||
import 'tcplayer.js/dist/tcplayer.min.css'; //引入插件和样式文件
|
||||
import { servicesTopic, services_replyTopic } from '@/utils/debugging/remote';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const props = defineProps({
|
||||
msgData: Object,
|
||||
});
|
||||
let player;
|
||||
watch(
|
||||
() => props.msgData,
|
||||
(val) => {
|
||||
if (val.topic == 'thing/product/8UUXN5400A079H/services_reply') {
|
||||
if (val.message.method == 'live_start_push') {
|
||||
console.log(val);
|
||||
if (val.message.data.result == 0) {
|
||||
createMessage.success('开始直播成功');
|
||||
player.src('http://175.27.168.120:6012/live/2.m3u8');
|
||||
} else if (val.message.data.result == 513003) {
|
||||
createMessage.success('直播已开启');
|
||||
player.src('http://175.27.168.120:6012/live/2.m3u8');
|
||||
} else {
|
||||
createMessage.error('开始直播失败');
|
||||
}
|
||||
} else if (val.message.method == 'live_stop_push') {
|
||||
if (val.message.data.result == 0) {
|
||||
createMessage.success('停止直播成功');
|
||||
if (player) {
|
||||
// player.dispose();
|
||||
}
|
||||
} else {
|
||||
createMessage.error('停止直播失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
const startLiveFun = () => {
|
||||
const querys = {
|
||||
urlType: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
url: 'rtmp://221.2.83.254:1935/live/2',
|
||||
//video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
videoId: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
bid: buildGUID(),
|
||||
method: 'live_start_push',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
url_type: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
url: 'rtmp://175.27.168.120:6019/live/2',
|
||||
//video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
video_id: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
video_quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
},
|
||||
};
|
||||
startLive(querys).then((res) => {
|
||||
console.log(res);
|
||||
servicesTopic(querys);
|
||||
services_replyTopic();
|
||||
// const querys = {
|
||||
// urlType: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
// url: 'rtmp://175.27.168.120:6019/live/2',
|
||||
// //video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
// videoId: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
// quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
// };
|
||||
// startLive(querys).then((res) => {
|
||||
// console.log(res);
|
||||
// player = TCPlayer('player-container-id', {
|
||||
// width: 360,
|
||||
// height: 200,
|
||||
// sources: [
|
||||
// {
|
||||
// src: 'http://175.27.168.120:6012/live/2.m3u8', // 播放地址
|
||||
// },
|
||||
// ],
|
||||
// licenseUrl: 'http://175.27.168.120:6012/live/2.m3u8', // license 地址,必传。参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
|
||||
// });
|
||||
// });
|
||||
};
|
||||
const closeLive = () => {
|
||||
const querys = {
|
||||
bid: buildGUID(),
|
||||
method: 'live_stop_push',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
video_id: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
},
|
||||
};
|
||||
servicesTopic(querys);
|
||||
// endLive({
|
||||
// videoId: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// player.dispose();
|
||||
// });
|
||||
};
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
startLiveFun();
|
||||
player = TCPlayer('player-container-id', {
|
||||
width: 360,
|
||||
height: 200,
|
||||
sources: [
|
||||
{
|
||||
src: 'http://221.2.83.254:7005/live/2.m3u8', // 播放地址
|
||||
src: 'http://175.27.168.120:6012/live/2.m3u8', // 播放地址
|
||||
},
|
||||
],
|
||||
licenseUrl: 'http://221.2.83.254:7005/live/2.m3u8', // license 地址,必传。参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
|
||||
licenseUrl: 'http://175.27.168.120:6012/live/2.m3u8', // license 地址,必传。参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
|
||||
});
|
||||
});
|
||||
};
|
||||
const closeLive = () => {
|
||||
endLive({
|
||||
videoId: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
player.dispose();
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
// startLiveFun();
|
||||
}, 1000);
|
||||
});
|
||||
// 销毁视频控件
|
||||
onBeforeUnmount(() => {
|
||||
|
|
@ -107,5 +179,11 @@
|
|||
border: 1px solid #3a57e8;
|
||||
}
|
||||
}
|
||||
.player {
|
||||
height: 200px;
|
||||
#player-container-id-live {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -8,38 +8,49 @@
|
|||
</div>
|
||||
<div class="content">
|
||||
<div class="content-button">
|
||||
<a-button>获取飞行器控制器</a-button>
|
||||
<a-button>一键起飞</a-button>
|
||||
<a-button @click="obtain">获取飞行器控制权</a-button>
|
||||
<a-button @click="emits('clickTakeOff')">一键起飞</a-button>
|
||||
<a-button>指点飞行</a-button>
|
||||
<a-button>智能环绕</a-button>
|
||||
<a-button>一键返航</a-button>
|
||||
<!-- <a-button>智能环绕</a-button> -->
|
||||
<a-button @click="returnVoyage">一键返航</a-button>
|
||||
</div>
|
||||
<div class="content-info">
|
||||
<div class="info-item">
|
||||
<img src="@/assets/images/flightoperation/flight_control.png" alt="" />
|
||||
<div class="info-item-top"></div>
|
||||
<div class="info-item-right"></div>
|
||||
<div class="info-item-bottom"></div>
|
||||
<div class="info-item-left"></div>
|
||||
<div class="info-item-top" title="上升" @click="changeDRC('throttle', 'up')"></div>
|
||||
<div class="info-item-right" title="右旋转" @click="changeDRC('yaw', 'up')"></div>
|
||||
<div class="info-item-bottom" title="下降" @click="changeDRC('throttle', 'down')"></div>
|
||||
<div class="info-item-left" title="左旋转" @click="changeDRC('yaw', 'down')"></div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<img src="@/assets/images/flightoperation/flight_control.png" alt="" />
|
||||
<div class="info-item-top"></div>
|
||||
<div class="info-item-right"></div>
|
||||
<div class="info-item-bottom"></div>
|
||||
<div class="info-item-left"></div>
|
||||
<div class="info-item-top" title="前进" @click="changeDRC('pitch', 'up')"></div>
|
||||
<div class="info-item-right" title="右移" @click="changeDRC('roll', 'up')"></div>
|
||||
<div class="info-item-bottom" title="后退" @click="changeDRC('pitch', 'down')"></div>
|
||||
<div class="info-item-left" title="左移" @click="changeDRC('roll', 'down')"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { onMounted, ref, watch, reactive } from 'vue';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { CloseOutlined } from '@ant-design/icons-vue';
|
||||
import { vDrag } from '@/utils/drag';
|
||||
import { getReizeClient, createSeizeConnection, clientReizePublish } from '@/utils/mqtt';
|
||||
import {
|
||||
eventsTopic,
|
||||
events_replyTopic,
|
||||
drcDownTopic,
|
||||
servicesTopic,
|
||||
return_home_status,
|
||||
} from '@/utils/debugging/events';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
|
||||
const emits = defineEmits(['changeFlightControl']);
|
||||
const { createMessage } = useMessage();
|
||||
const emits = defineEmits(['changeFlightControl', 'clickTakeOff']);
|
||||
const props = defineProps({
|
||||
airportAllVal: Object,
|
||||
});
|
||||
|
|
@ -58,6 +69,13 @@
|
|||
capacity_percent: 0,
|
||||
},
|
||||
});
|
||||
const data = reactive({
|
||||
roll: 1024,
|
||||
pitch: 1024,
|
||||
throttle: 1024,
|
||||
yaw: 1024,
|
||||
gimbal_pitch: 1024,
|
||||
});
|
||||
watch(
|
||||
() => props.airportAllVal,
|
||||
(val) => {
|
||||
|
|
@ -65,6 +83,65 @@
|
|||
airportVal.value = val.data;
|
||||
},
|
||||
);
|
||||
// 获取
|
||||
const obtain = () => {
|
||||
if (!getReizeClient()) {
|
||||
createSeizeConnection();
|
||||
}
|
||||
setTimeout(() => {
|
||||
// 飞行控制权抢夺
|
||||
eventsTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'flight_authority_grab',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {},
|
||||
});
|
||||
// 负载控制权抢夺
|
||||
eventsTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'payload_authority_grab',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
payload_index: '99-0-0',
|
||||
},
|
||||
});
|
||||
events_replyTopic();
|
||||
// // 接收消息
|
||||
getReizeClient().on('message', (topic, message) => {
|
||||
const rs = JSON.parse(message);
|
||||
console.log(rs);
|
||||
// 一键返航
|
||||
if (rs.method === 'return_home') {
|
||||
createMessage.info(return_home_status[rs.data.output.status]);
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
// 一键返航
|
||||
const returnVoyage = () => {
|
||||
servicesTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'return_home',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {},
|
||||
});
|
||||
};
|
||||
const changeDRC = (type, value) => {
|
||||
if (value == 'up') {
|
||||
data[type] = data[type] + 20;
|
||||
} else {
|
||||
data[type] = data[type] - 20;
|
||||
}
|
||||
const querys = {
|
||||
seq: 1,
|
||||
method: 'stick_control',
|
||||
data: data,
|
||||
};
|
||||
drcDownTopic(querys);
|
||||
};
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<div class="preview-title">
|
||||
<div class="title-select">
|
||||
<div class="title-select-item">
|
||||
<span>镜头:</span>
|
||||
<a-select
|
||||
ref="select"
|
||||
v-model:value="selectVal.camera"
|
||||
|
|
@ -23,9 +24,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="title-icon">
|
||||
<RedoOutlined />
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<ExpandOutlined />
|
||||
<RedoOutlined @click="startLiveFun" />
|
||||
<!-- <a-divider type="vertical" style="border-color: #4e5778" /> -->
|
||||
<!-- <ExpandOutlined /> -->
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<PoweroffOutlined @click="closeLive" />
|
||||
</div>
|
||||
|
|
@ -46,7 +47,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { RedoOutlined, ExpandOutlined, PoweroffOutlined } from '@ant-design/icons-vue';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { reactive, onMounted, ref, watch } from 'vue';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import {
|
||||
|
|
@ -57,21 +58,79 @@
|
|||
} from '@/api/workmanagement/airportMaintenance';
|
||||
import TCPlayer from 'tcplayer.js';
|
||||
import 'tcplayer.js/dist/tcplayer.min.css'; //引入插件和样式文件
|
||||
import { servicesUAVTopic, services_replyUAVTopic } from '@/utils/debugging/remote';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const props = defineProps({
|
||||
msgData: Object,
|
||||
});
|
||||
let player;
|
||||
watch(
|
||||
() => props.msgData,
|
||||
(val) => {
|
||||
if (val.topic == 'thing/product/1581F8HGX254V00A0BUY/services_reply') {
|
||||
if (val.message.method == 'live_start_push') {
|
||||
console.log(val);
|
||||
if (val.message.data.result == 0) {
|
||||
createMessage.success('开始直播成功');
|
||||
player.src('http://175.27.168.120:6012/live/3.m3u8');
|
||||
} else if (val.message.data.result == 513003) {
|
||||
createMessage.success('直播已开启');
|
||||
player.src('http://175.27.168.120:6012/live/3.m3u8');
|
||||
} else {
|
||||
createMessage.error('开始直播失败');
|
||||
}
|
||||
} else if (val.message.method == 'live_stop_push') {
|
||||
if (val.message.data.result == 0) {
|
||||
createMessage.success('停止直播成功');
|
||||
if (player) {
|
||||
// player.dispose();
|
||||
}
|
||||
} else {
|
||||
createMessage.error('停止直播失败');
|
||||
}
|
||||
} else if (val.message.method == 'live_set_quality') {
|
||||
if (val.message.data.result == 0) {
|
||||
createMessage.success('设置清晰度成功');
|
||||
player.src('http://175.27.168.120:6012/live/3.m3u8');
|
||||
} else {
|
||||
createMessage.error('设置清晰度失败');
|
||||
}
|
||||
} else if (val.message.method == 'live_lens_change') {
|
||||
console.log(val);
|
||||
|
||||
if (val.message.data.result == 0) {
|
||||
createMessage.success('设置直播镜头成功');
|
||||
player.src('http://175.27.168.120:6012/live/3.m3u8');
|
||||
} else {
|
||||
createMessage.error('设置直播镜头失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
const selectVal = reactive({
|
||||
camera: 1,
|
||||
camera: 'normal',
|
||||
resolution: 1,
|
||||
});
|
||||
const optionsArr = reactive({
|
||||
cameraOptions: [
|
||||
{
|
||||
label: '相机',
|
||||
value: 0,
|
||||
label: '红外',
|
||||
value: 'ir',
|
||||
},
|
||||
{
|
||||
label: '直播',
|
||||
value: 1,
|
||||
label: '默认',
|
||||
value: 'normal',
|
||||
},
|
||||
{
|
||||
label: '广角',
|
||||
value: 'wide',
|
||||
},
|
||||
{
|
||||
label: '变焦',
|
||||
value: 'zoom',
|
||||
},
|
||||
],
|
||||
resolutionOptions: [
|
||||
|
|
@ -99,38 +158,77 @@
|
|||
});
|
||||
const startLiveFun = () => {
|
||||
const querys = {
|
||||
urlType: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
url: 'rtmp://221.2.83.254:1935/live/3',
|
||||
//video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
bid: buildGUID(),
|
||||
method: 'live_start_push',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
url_type: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
url: 'rtmp://175.27.168.120:6019/live/3',
|
||||
//video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
video_id: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
video_quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
},
|
||||
};
|
||||
startLive(querys).then((res) => {
|
||||
console.log(res);
|
||||
playVideo();
|
||||
});
|
||||
servicesUAVTopic(querys);
|
||||
services_replyUAVTopic();
|
||||
// const querys = {
|
||||
// urlType: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
// // url: 'rtmp://221.2.83.254:1935/live/3',
|
||||
// url: 'rtmp://175.27.168.120:6019/live/3',
|
||||
// //video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
// videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
// quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
// };
|
||||
// startLive(querys).then((res) => {
|
||||
// console.log(res);
|
||||
// playVideo();
|
||||
// });
|
||||
};
|
||||
const resolutionChange = (val: any) => {
|
||||
const querys = {
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
videoQuality: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
bid: buildGUID(),
|
||||
method: 'live_set_quality',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
video_id: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
video_quality: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
},
|
||||
};
|
||||
setCameraVideo(querys).then((res) => {
|
||||
console.log(res);
|
||||
playVideo();
|
||||
});
|
||||
servicesUAVTopic(querys);
|
||||
// const querys = {
|
||||
// videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
// videoQuality: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
// };
|
||||
// setCameraVideo(querys).then((res) => {
|
||||
// console.log(res);
|
||||
// playVideo();
|
||||
// });
|
||||
};
|
||||
const cameraChange = (val: any) => {
|
||||
console.log(val);
|
||||
const requestData = {
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
position: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
camera: '99-0-0',
|
||||
const querys = {
|
||||
bid: buildGUID(),
|
||||
method: 'live_lens_change',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
video_id: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
video_type: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
},
|
||||
};
|
||||
exchangeCamera(requestData).then((res) => {
|
||||
console.log(res);
|
||||
playVideo();
|
||||
});
|
||||
console.log(querys);
|
||||
servicesUAVTopic(querys);
|
||||
// const requestData = {
|
||||
// videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
// position: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
// camera: '99-0-0',
|
||||
// };
|
||||
// exchangeCamera(requestData).then((res) => {
|
||||
// console.log(res);
|
||||
// playVideo();
|
||||
// });
|
||||
};
|
||||
const data = reactive({
|
||||
playedTime: 0,
|
||||
|
|
@ -143,21 +241,34 @@
|
|||
height: 180,
|
||||
sources: [
|
||||
{
|
||||
src: 'http://221.2.83.254:7005/live/3.m3u8', // 播放地址
|
||||
src: 'http://175.27.168.120:6012/live/3.m3u8', // 播放地址
|
||||
},
|
||||
],
|
||||
licenseUrl: 'http://221.2.83.254:7005/live/3.m3u8', // license 地址,必传。参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
|
||||
licenseUrl: 'http://175.27.168.120:6012/live/3.m3u8', // license 地址,必传。参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
|
||||
});
|
||||
};
|
||||
const closeLive = () => {
|
||||
endLive({
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
const querys = {
|
||||
bid: buildGUID(),
|
||||
method: 'live_stop_push',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
video_id: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
},
|
||||
};
|
||||
servicesUAVTopic(querys);
|
||||
// endLive({
|
||||
// videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
};
|
||||
onMounted(() => {
|
||||
// startLiveFun();
|
||||
setTimeout(() => {
|
||||
startLiveFun();
|
||||
playVideo();
|
||||
}, 1000);
|
||||
// resolutionChange(1);
|
||||
});
|
||||
</script>
|
||||
|
|
@ -241,5 +352,11 @@
|
|||
top: 100px;
|
||||
z-index: 3;
|
||||
}
|
||||
.player {
|
||||
height: 180px;
|
||||
#player-container-id-live {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -21,10 +21,22 @@
|
|||
</div>
|
||||
<div class="direction-controller">
|
||||
<img src="@/assets/images/flightoperation/direction_controller.png" alt="" />
|
||||
<div class="direction-controller-top" @click="changeDrc('top')"></div>
|
||||
<div class="direction-controller-right" @click="changeDrc('right')"></div>
|
||||
<div class="direction-controller-bottom" @click="changeDrc('bottom')"></div>
|
||||
<div class="direction-controller-left" @click="changeDrc('left')"></div>
|
||||
<div class="direction-controller-top" title="前进" @click="changeDrc('pitch', 'top')"></div>
|
||||
<div
|
||||
class="direction-controller-right"
|
||||
title="右移"
|
||||
@click="changeDrc('roll', 'right')"
|
||||
></div>
|
||||
<div
|
||||
class="direction-controller-bottom"
|
||||
title="后退"
|
||||
@click="changeDrc('pitch', 'bottom')"
|
||||
></div>
|
||||
<div
|
||||
class="direction-controller-left"
|
||||
title="左移"
|
||||
@click="changeDrc('roll', 'left')"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -73,25 +85,30 @@
|
|||
);
|
||||
|
||||
const obtain = () => {
|
||||
// 飞行控制权抢夺
|
||||
eventsTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'flight_authority_grab',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {},
|
||||
});
|
||||
// 负载控制权抢夺
|
||||
eventsTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'payload_authority_grab',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
payload_index: '99-0-0',
|
||||
},
|
||||
});
|
||||
events_replyTopic();
|
||||
if (!getReizeClient()) {
|
||||
createSeizeConnection();
|
||||
}
|
||||
setTimeout(() => {
|
||||
// 飞行控制权抢夺
|
||||
eventsTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'flight_authority_grab',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {},
|
||||
});
|
||||
// 负载控制权抢夺
|
||||
eventsTopic({
|
||||
bid: buildGUID(),
|
||||
method: 'payload_authority_grab',
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
payload_index: '99-0-0',
|
||||
},
|
||||
});
|
||||
events_replyTopic();
|
||||
}, 1000);
|
||||
};
|
||||
// 单拍
|
||||
const singleShot = () => {
|
||||
|
|
@ -107,15 +124,11 @@
|
|||
});
|
||||
};
|
||||
// 控制方向
|
||||
const changeDrc = (val) => {
|
||||
if (val == 'top') {
|
||||
drcVal.pitch = drcVal.pitch + 20;
|
||||
} else if (val == 'bottom') {
|
||||
drcVal.pitch = drcVal.pitch - 20;
|
||||
} else if (val == 'left') {
|
||||
drcVal.roll = drcVal.roll - 20;
|
||||
} else if (val == 'right') {
|
||||
drcVal.roll = drcVal.roll + 20;
|
||||
const changeDrc = (type, val) => {
|
||||
if (val == 'up') {
|
||||
drcVal[type] = drcVal[type] + 20;
|
||||
} else {
|
||||
drcVal[type] = drcVal[type] - 20;
|
||||
}
|
||||
const querys = {
|
||||
seq: 1,
|
||||
|
|
@ -125,7 +138,6 @@
|
|||
drcDownTopic(querys);
|
||||
};
|
||||
onMounted(() => {
|
||||
// createSeizeConnection();
|
||||
// // 接收消息
|
||||
// getReizeClient().on('message', (topic, message) => {
|
||||
// const rs = JSON.parse(message);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,289 @@
|
|||
<template>
|
||||
<div class="takeoff-information">
|
||||
<div class="title"
|
||||
>一键起飞
|
||||
<div @click="emits('changeTakeOffForm')">
|
||||
<CloseOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-edit">
|
||||
目标点纬度
|
||||
<div>
|
||||
<a-input v-model:value="data.target_latitude" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
目标点经度
|
||||
<div>
|
||||
<a-input v-model:value="data.target_longitude" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
目标点高度
|
||||
<div>
|
||||
<a-input v-model:value="data.target_height" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
安全起飞高度
|
||||
<div>
|
||||
<a-input v-model:value="data.security_takeoff_height" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
返航模式
|
||||
<div>
|
||||
<a-select v-model:value="data.rth_mode" :options="rth_modeOptions" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
返航高度
|
||||
<div>
|
||||
<a-input v-model:value="data.rth_altitude" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
遥控器失控动作
|
||||
<div>
|
||||
<a-select v-model:value="data.rc_lost_action" :options="rc_lost_actionOptions" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
指点飞行失控动作
|
||||
<div>
|
||||
<a-select
|
||||
v-model:value="data.commander_mode_lost_action"
|
||||
:options="commander_mode_lost_actionOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
指点飞行模式
|
||||
<div>
|
||||
<a-select
|
||||
v-model:value="data.commander_flight_mode"
|
||||
:options="commander_flight_modeOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
指点飞行高度
|
||||
<div>
|
||||
<a-input v-model:value="data.commander_flight_height" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-button">
|
||||
<a-button
|
||||
type="primary"
|
||||
style="background: #0a99eb; width: 40%"
|
||||
@click="emits('changeTakeOffForm')"
|
||||
>关闭</a-button
|
||||
>
|
||||
<a-button type="primary" style="background: #3a57e8; width: 40%" @click="takeOff"
|
||||
>起飞</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { CopyOutlined, EditOutlined } from '@ant-design/icons-vue';
|
||||
import { timestampToFormattedDate } from '@/utils/index';
|
||||
import { buildGUID, uuid } from '@/utils/uuid';
|
||||
import { servicesTopic, services_replyTopic } from '@/utils/debugging/events';
|
||||
import { vDrag } from '@/utils/drag';
|
||||
import { CloseOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
const emits = defineEmits(['changeTakeOffForm']);
|
||||
const props = defineProps({
|
||||
msgData: Object,
|
||||
});
|
||||
const data = reactive({
|
||||
flight_id: uuid(14, 14),
|
||||
target_latitude: 35.134615,
|
||||
target_longitude: 118.296676,
|
||||
target_height: 115,
|
||||
security_takeoff_height: 100,
|
||||
rth_altitude: 115,
|
||||
rth_mode: 1,
|
||||
max_speed: 10,
|
||||
commander_flight_mode: 1,
|
||||
rc_lost_action: 2,
|
||||
commander_mode_lost_action: 1,
|
||||
commander_flight_height: 115.0,
|
||||
flight_safety_advance_check: 1,
|
||||
simulate_mission: {
|
||||
is_enable: 1, // 是否开启模拟任务{"0":"不开启","1":"开启"}
|
||||
latitude: 35.143567, // 模拟器纬度
|
||||
longitude: 118.305623, // 模拟器经度
|
||||
},
|
||||
});
|
||||
const uavInformation = ref({
|
||||
sub_device: {
|
||||
// 飞行器状态
|
||||
device_online_status: 0,
|
||||
},
|
||||
drone_battery_maintenance_info: {
|
||||
// 电池剩余电量
|
||||
capacity_percent: 0,
|
||||
},
|
||||
wireless_link: {
|
||||
// 飞行器上 Dongle 数量
|
||||
dongle_number: 0,
|
||||
sdr_quality: 0,
|
||||
'4g_quality': 0,
|
||||
'4g_uav_quality': 0,
|
||||
'4g_gnd_quality': 0,
|
||||
remain_upload: 0,
|
||||
sdr_link_state: 0,
|
||||
sdr_freq_band: 0,
|
||||
},
|
||||
});
|
||||
const time = ref(timestampToFormattedDate(new Date().getTime()));
|
||||
const rth_modeOptions = ref([
|
||||
{ label: '智能高度', value: 0 },
|
||||
{ label: '设定高度', value: 1 },
|
||||
]);
|
||||
const rc_lost_actionOptions = ref([
|
||||
{ label: '悬停', value: 0 },
|
||||
{ label: '着陆(降落)', value: 1 },
|
||||
{ label: '返航', value: 2 },
|
||||
]);
|
||||
const commander_mode_lost_actionOptions = ref([
|
||||
{ label: '继续执行指点飞行任务', value: 0 },
|
||||
{ label: '退出指点飞行任务,执行普通失控行为', value: 1 },
|
||||
]);
|
||||
const commander_flight_modeOptions = ref([
|
||||
{ label: '智能高度飞行', value: 0 },
|
||||
{ label: '设定高度飞行', value: 1 },
|
||||
]);
|
||||
watch(
|
||||
() => props.msgData,
|
||||
(val) => {
|
||||
if (val.topic == 'thing/product/8UUXN5400A079H/osd') {
|
||||
if (
|
||||
val.message.data.sub_device ||
|
||||
val.message.data.drone_battery_maintenance_info ||
|
||||
val.message.data.wireless_link
|
||||
) {
|
||||
// console.log(val);
|
||||
uavInformation.value = val.message.data;
|
||||
time.value = timestampToFormattedDate(val.message.timestamp);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
const takeOff = () => {
|
||||
const querys = {
|
||||
bid: buildGUID(),
|
||||
data: data,
|
||||
tid: buildGUID(),
|
||||
timestamp: new Date().getTime(),
|
||||
method: 'takeoff_to_point',
|
||||
};
|
||||
console.log(querys);
|
||||
// servicesTopic(querys);
|
||||
setTimeout(() => {
|
||||
emits('changeTakeOffForm');
|
||||
}, 1000);
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.takeoff-information {
|
||||
position: absolute;
|
||||
top: 120px;
|
||||
left: 300px;
|
||||
z-index: 999;
|
||||
width: 460px;
|
||||
padding: 10px;
|
||||
background: #0d0e15;
|
||||
margin: 10px 0 0 10px;
|
||||
box-shadow:
|
||||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
.title {
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-bottom: 1px solid #4e5778;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.content-title {
|
||||
font-size: 14px;
|
||||
padding: 10px 0;
|
||||
span {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.content-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #4e5778;
|
||||
padding: 10px 0;
|
||||
.item-div {
|
||||
width: 49%;
|
||||
img {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-button {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.content-edit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
// border: 1px solid #4e5778;
|
||||
margin-top: 10px;
|
||||
padding: 2px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
input {
|
||||
background: none;
|
||||
width: 260px;
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
::v-deep .ant-input-number,
|
||||
.ant-input-number-group-wrapper {
|
||||
background: none;
|
||||
width: 260px !important;
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
::v-deep .ant-input-number-group-wrapper {
|
||||
input {
|
||||
background: none;
|
||||
width: 260px !important;
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
::v-deep .ant-select-selector {
|
||||
background: none;
|
||||
width: 260px;
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue