Merge branch 'v1.7.0'
Esse commit está contido em:
@@ -18,6 +18,18 @@ export enum LostControlActionInCommandFLight {
|
||||
Land = 1, // 着陆
|
||||
RETURN_HOME = 2, // 返航
|
||||
}
|
||||
export enum ERthMode {
|
||||
SMART = 0,
|
||||
SETTING = 1
|
||||
}
|
||||
export enum ECommanderModeLostAction {
|
||||
CONTINUE = 0,
|
||||
EXEC_LOST_ACTION = 1
|
||||
}
|
||||
export enum ECommanderFlightMode {
|
||||
SMART = 0,
|
||||
SETTING = 1
|
||||
}
|
||||
export interface PointBody {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
@@ -48,7 +60,11 @@ export interface PostTakeoffToPointBody{
|
||||
max_speed: number; // flyto过程中能达到的最大速度, 单位m/s 跟飞机档位有关
|
||||
rc_lost_action: LostControlActionInCommandFLight; // 失控行为
|
||||
rth_altitude: number; // 返航高度
|
||||
exit_wayline_when_rc_lost: WaylineLostControlActionInCommandFlight
|
||||
exit_wayline_when_rc_lost: WaylineLostControlActionInCommandFlight;
|
||||
rth_mode: ERthMode;
|
||||
commander_mode_lost_action: ECommanderModeLostAction;
|
||||
commander_flight_mode: ECommanderFlightMode;
|
||||
commander_flight_height: number;
|
||||
}
|
||||
|
||||
// 一键起飞
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
export const CURRENT_CONFIG = {
|
||||
|
||||
// license
|
||||
appId: 'Please enter the app id.', // You need to go to the development website to apply.
|
||||
appKey: 'Please enter the app key.', // You need to go to the development website to apply.
|
||||
appId: 'Please enter the app id.', // You need to go to the development website to apply.
|
||||
appKey: 'Please enter the app key.', // You need to go to the development website to apply.
|
||||
appLicense: 'Please enter the app license.', // You need to go to the development website to apply.
|
||||
|
||||
|
||||
// http
|
||||
baseURL: 'Please enter the backend access address prefix.', // This url must end with "/". Example: 'http://192.168.1.1:6789/'
|
||||
websocketURL: 'Please enter the WebSocket access address.', // Example: 'ws://192.168.1.1:6789/api/v1/ws'
|
||||
websocketURL: 'Please enter the WebSocket access address.', // Example: 'ws://192.168.1.1:6789/api/v1/ws'
|
||||
|
||||
// livestreaming
|
||||
// RTMP Note: This IP is the address of the streaming server. If you want to see livestream on web page, you need to convert the RTMP stream to WebRTC stream.
|
||||
rtmpURL: 'Please enter the rtmp access address.', // Example: 'rtmp://192.168.1.1/live/'
|
||||
rtmpURL: 'Please enter the rtmp access address.', // Example: 'rtmp://192.168.1.1/live/'
|
||||
// GB28181 Note:If you don't know what these parameters mean, you can go to Pilot2 and select the GB28181 page in the cloud platform. Where the parameters same as these parameters.
|
||||
gbServerIp: 'Please enter the server ip.',
|
||||
gbServerPort: 'Please enter the server port.',
|
||||
@@ -29,7 +29,7 @@ export const CURRENT_CONFIG = {
|
||||
agoraToken: 'Please enter the agora temporary token.',
|
||||
agoraChannel: 'Please enter the agora channel.',
|
||||
|
||||
// map
|
||||
// map
|
||||
// You can apply on the AMap website.
|
||||
amapKey: 'Please enter the amap key.',
|
||||
|
||||
|
||||
@@ -42,10 +42,12 @@ export interface CreatePlan {
|
||||
dock_sn: string,
|
||||
task_type: TaskType, // 任务类型
|
||||
wayline_type: WaylineType, // 航线类型
|
||||
task_days?: number[] // 执行任务的日期(秒)
|
||||
task_periods?: number[][] // 执行任务的时间点(秒)
|
||||
task_days: number[] // 执行任务的日期(秒)
|
||||
task_periods: number[][] // 执行任务的时间点(秒)
|
||||
rth_altitude: number // 相对机场返航高度 20 - 500
|
||||
out_of_control_action: OutOfControlAction // 失控动作
|
||||
min_battery_capacity?: number, // The minimum battery capacity of aircraft.
|
||||
min_storage_capacity?: number, // The minimum storage capacity of dock and aircraft.
|
||||
}
|
||||
|
||||
// Create Wayline Job
|
||||
|
||||
+87
-31
@@ -21,8 +21,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 飞机OSD -->
|
||||
<div v-if="osdVisible.visible && !osdVisible.is_dock" class="osd-panel fz12">
|
||||
<div class="pl5 pr5 flex-align-center flex-row flex-justify-between" style="border-bottom: 1px solid #515151; height: 18%;">
|
||||
<div v-if="osdVisible.visible && !osdVisible.is_dock" v-drag-window class="osd-panel fz12">
|
||||
<div class="drag-title pl5 pr5 flex-align-center flex-row flex-justify-between" style="border-bottom: 1px solid #515151; height: 18%;">
|
||||
<span>{{ osdVisible.callsign }}</span>
|
||||
<span><a class="fz16" style="color: white;" @click="() => osdVisible.visible = false"><CloseOutlined /></a></span>
|
||||
</div>
|
||||
@@ -49,7 +49,7 @@
|
||||
<a-col span="6">
|
||||
<a-tooltip title="RC Battery Level">
|
||||
<span><ThunderboltOutlined class="fz14"/></span>
|
||||
<span class="ml10">{{ deviceInfo.gateway && deviceInfo.gateway.capacity_percent !== str ? deviceInfo.gateway.capacity_percent + ' %' : deviceInfo.gateway.capacity_percent }}</span>
|
||||
<span class="ml10">{{ deviceInfo.gateway && deviceInfo.gateway.capacity_percent !== str ? deviceInfo.gateway?.capacity_percent + ' %' : deviceInfo.gateway?.capacity_percent }}</span>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
|
||||
@@ -141,11 +141,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 机场OSD -->
|
||||
<div v-if="osdVisible.visible && osdVisible.is_dock" class="osd-panel fz12">
|
||||
<div class="fz16 pl5 pr5 flex-align-center flex-row flex-justify-between" style="border-bottom: 1px solid #515151; height: 10%;">
|
||||
<div v-if="osdVisible.visible && osdVisible.is_dock" v-drag-window class="osd-panel fz12">
|
||||
<div class="drag-title fz16 pl5 pr5 flex-align-center flex-row flex-justify-between" style="border-bottom: 1px solid #515151; height: 10%;">
|
||||
<span>{{ osdVisible.gateway_callsign }}</span>
|
||||
<span><a style="color: white;" @click="() => osdVisible.visible = false"><CloseOutlined /></a></span>
|
||||
</div>
|
||||
<span><a style="color: white; position: absolute; top: 5px; right: 5px;" @click="() => osdVisible.visible = false"><CloseOutlined /></a></span>
|
||||
<!-- 机场 -->
|
||||
<div class ="flex-display" style="border-bottom: 1px solid #515151;">
|
||||
<div class="flex-column flex-align-stretch flex-justify-center" style="width: 60px; background: #2d2d2d;">
|
||||
@@ -267,7 +267,7 @@
|
||||
<a-col span="6">
|
||||
<a-tooltip title="Drone in dock">
|
||||
<span><RocketOutlined /></span>
|
||||
<span class="ml10">{{ DroneInDockEnum[deviceInfo.dock.basic_osd?.drone_in_dock] }}</span>
|
||||
<span class="ml10">{{ deviceInfo.dock.basic_osd?.drone_in_dock }}</span>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -413,6 +413,17 @@
|
||||
<!-- 飞行指令 -->
|
||||
<DroneControlPanel :sn="osdVisible.gateway_sn" :deviceInfo="deviceInfo" :payloads="osdVisible.payloads"></DroneControlPanel>
|
||||
</div>
|
||||
<!-- liveview -->
|
||||
<div class="liveview" v-if="livestreamOthersVisible" v-drag-window >
|
||||
<div style="height: 40px; width: 100%" class="drag-title"></div>
|
||||
<a style="position: absolute; right: 10px; top: 10px; font-size: 16px; color: white;" @click="closeLivestreamOthers"><CloseOutlined /></a>
|
||||
<LivestreamOthers />
|
||||
</div>
|
||||
<div class="liveview" v-if="livestreamAgoraVisible" v-drag-window >
|
||||
<div style="height: 40px; width: 100%" class="drag-title"></div>
|
||||
<a style="position: absolute; right: 10px; top: 10px; font-size: 16px; color: white;" @click="closeLivestreamAgora"><CloseOutlined /></a>
|
||||
<LivestreamAgora />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -452,6 +463,8 @@ import DockControlPanel from './g-map/DockControlPanel.vue'
|
||||
import { useDockControl } from './g-map/use-dock-control'
|
||||
import DroneControlPanel from './g-map/DroneControlPanel.vue'
|
||||
import { useConnectMqtt } from './g-map/use-connect-mqtt'
|
||||
import LivestreamOthers from './livestream-others.vue'
|
||||
import LivestreamAgora from './livestream-agora.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -475,7 +488,9 @@ export default defineComponent({
|
||||
DockControlPanel,
|
||||
DroneControlPanel,
|
||||
CarryOutOutlined,
|
||||
RocketOutlined
|
||||
RocketOutlined,
|
||||
LivestreamOthers,
|
||||
LivestreamAgora
|
||||
},
|
||||
name: 'GMap',
|
||||
props: {},
|
||||
@@ -534,6 +549,12 @@ export default defineComponent({
|
||||
const drawVisible = computed(() => {
|
||||
return store.state.drawVisible
|
||||
})
|
||||
const livestreamOthersVisible = computed(() => {
|
||||
return store.state.livestreamOthersVisible
|
||||
})
|
||||
const livestreamAgoraVisible = computed(() => {
|
||||
return store.state.livestreamAgoraVisible
|
||||
})
|
||||
const osdVisible = computed(() => {
|
||||
return store.state.osdVisible
|
||||
})
|
||||
@@ -572,7 +593,7 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
if (data.currentType === EDeviceTypeName.Dock && data.dockInfo[data.currentSn]) {
|
||||
deviceTsaUpdateHook.initMarker(EDeviceTypeName.Dock, [EDeviceTypeName.Dock], data.currentSn, data.dockInfo[data.currentSn].basic_osd?.longitude, data.dockInfo[data.currentSn].basic_osd?.latitude)
|
||||
deviceTsaUpdateHook.initMarker(EDeviceTypeName.Dock, EDeviceTypeName[EDeviceTypeName.Dock], data.currentSn, data.dockInfo[data.currentSn].basic_osd?.longitude, data.dockInfo[data.currentSn].basic_osd?.latitude)
|
||||
if (osdVisible.value.visible && osdVisible.value.is_dock && osdVisible.value.gateway_sn !== '') {
|
||||
deviceInfo.dock = data.dockInfo[osdVisible.value.gateway_sn]
|
||||
deviceInfo.device = data.deviceInfo[deviceInfo.dock.basic_osd.sub_device?.device_sn ?? osdVisible.value.sn]
|
||||
@@ -607,15 +628,27 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
updateCoordinates('wgs84-gcj02', ele)
|
||||
useGMapCoverHook.init2DPin(
|
||||
ele.name,
|
||||
ele.resource.content.geometry.coordinates,
|
||||
ele.resource.content.properties.color,
|
||||
{
|
||||
id: ele.id,
|
||||
name: ele.name
|
||||
}
|
||||
)
|
||||
const data = { id: ele.id, name: ele.name }
|
||||
if (MapElementEnum.PIN === ele.resource?.type) {
|
||||
useGMapCoverHook.init2DPin(
|
||||
ele.name,
|
||||
ele.resource.content.geometry.coordinates,
|
||||
ele.resource.content.properties.color,
|
||||
data
|
||||
)
|
||||
} else if (MapElementEnum.LINE === ele.resource?.type) {
|
||||
useGMapCoverHook.initPolyline(
|
||||
ele.name,
|
||||
ele.resource.content.geometry.coordinates,
|
||||
ele.resource.content.properties.color,
|
||||
data)
|
||||
} else if (MapElementEnum.POLY === ele.resource?.type) {
|
||||
useGMapCoverHook.initPolygon(
|
||||
ele.name,
|
||||
ele.resource.content.geometry.coordinates,
|
||||
ele.resource.content.properties.color,
|
||||
data)
|
||||
}
|
||||
}
|
||||
|
||||
store.state.wsEvent.mapElementCreat = {}
|
||||
@@ -749,6 +782,12 @@ export default defineComponent({
|
||||
console.log('layers', layers)
|
||||
store.commit('SET_LAYER_INFO', layers)
|
||||
}
|
||||
function closeLivestreamOthers () {
|
||||
store.commit('SET_LIVESTREAM_OTHERS_VISIBLE', false)
|
||||
}
|
||||
function closeLivestreamAgora () {
|
||||
store.commit('SET_LIVESTREAM_AGORA_VISIBLE', false)
|
||||
}
|
||||
function updateCoordinates (transformType: string, element: any) {
|
||||
const geoType = element.resource?.content.geometry.type
|
||||
const type = element.resource?.type as number
|
||||
@@ -769,39 +808,38 @@ export default defineComponent({
|
||||
) as GeojsonCoordinate
|
||||
element.resource.content.geometry.coordinates = transResult
|
||||
}
|
||||
} else if (MapElementEnum.LINE === type && geoType === 'LineString') {
|
||||
} else if (MapElementEnum.LINE === type) {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates as GeojsonCoordinate[]
|
||||
if (transformType === 'wgs84-gcj02') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = wgs84togcj02(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = wgs84togcj02(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
})
|
||||
} else if (transformType === 'gcj02-wgs84') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = gcj02towgs84(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = gcj02towgs84(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
})
|
||||
}
|
||||
element.resource.content.geometry.coordinates = coordinates
|
||||
} else if (MapElementEnum.LINE === type && geoType === 'Polygon') {
|
||||
} else if (MapElementEnum.POLY === type) {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates[0] as GeojsonCoordinate[]
|
||||
|
||||
if (transformType === 'wgs84-gcj02') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = wgs84togcj02(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = wgs84togcj02(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
})
|
||||
} else if (transformType === 'gcj02-wgs84') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = gcj02towgs84(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = gcj02towgs84(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
@@ -815,6 +853,8 @@ export default defineComponent({
|
||||
draw,
|
||||
mouseMode,
|
||||
drawVisible,
|
||||
livestreamOthersVisible,
|
||||
livestreamAgoraVisible,
|
||||
osdVisible,
|
||||
pin,
|
||||
state,
|
||||
@@ -830,7 +870,9 @@ export default defineComponent({
|
||||
NetworkStateTypeEnum,
|
||||
NetworkStateQualityEnum,
|
||||
RainfallEnum,
|
||||
DroneInDockEnum
|
||||
DroneInDockEnum,
|
||||
closeLivestreamOthers,
|
||||
closeLivestreamAgora
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -875,7 +917,8 @@ export default defineComponent({
|
||||
}
|
||||
.osd-panel {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
margin-left: 10px;
|
||||
left: 0;
|
||||
top: 10px;
|
||||
width: 480px;
|
||||
background: #000;
|
||||
@@ -926,4 +969,17 @@ export default defineComponent({
|
||||
min-height: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.liveview {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
margin-left: 10px;
|
||||
top: 10px;
|
||||
text-align: center;
|
||||
width: 800px;
|
||||
height: 720px;
|
||||
background: #232323;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -73,15 +73,14 @@ watch(() => props.deviceInfo, (value) => {
|
||||
deep: true
|
||||
})
|
||||
|
||||
// dock 控制指令
|
||||
const debugStatus = ref(props.deviceInfo.dock?.basic_osd?.mode_code === EDockModeCode.Remote_Debugging)
|
||||
const emit = defineEmits(['close-control-panel'])
|
||||
|
||||
function closeControlPanel () {
|
||||
emit('close-control-panel', props.sn)
|
||||
emit('close-control-panel', props.sn, debugStatus.value)
|
||||
}
|
||||
|
||||
// dock 控制指令
|
||||
const debugStatus = ref(props.deviceInfo.dock?.basic_osd.mode_code === EDockModeCode.Remote_Debugging)
|
||||
|
||||
async function onDeviceStatusChange (status: boolean) {
|
||||
let result = false
|
||||
if (status) {
|
||||
|
||||
@@ -112,15 +112,53 @@
|
||||
:options="WaylineLostControlActionInCommandFlightOptions"
|
||||
></a-select>
|
||||
</div>
|
||||
<div>
|
||||
<span class="form-label">Return-to-Home Mode:</span>
|
||||
<a-select
|
||||
v-model:value="takeoffToPointPopoverData.rthMode"
|
||||
style="width: 120px"
|
||||
:options="RthModeInCommandFlightOptions"
|
||||
></a-select>
|
||||
</div>
|
||||
<div>
|
||||
<span class="form-label">Commander Mode Lost Action:</span>
|
||||
<a-select
|
||||
v-model:value="takeoffToPointPopoverData.commanderModeLostAction"
|
||||
style="width: 120px"
|
||||
:options="CommanderModeLostActionInCommandFlightOptions"
|
||||
></a-select>
|
||||
</div>
|
||||
<div>
|
||||
<span class="form-label">Commander Flight Mode:</span>
|
||||
<a-select
|
||||
v-model:value="takeoffToPointPopoverData.commanderFlightMode"
|
||||
style="width: 120px"
|
||||
:options="CommanderFlightModeInCommandFlightOptions"
|
||||
></a-select>
|
||||
</div>
|
||||
<div>
|
||||
<span class="form-label">Commander Flight Height(m):</span>
|
||||
<a-input-number v-model:value="takeoffToPointPopoverData.commanderFlightHeight"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<Button size="small" ghost @click="onShowTakeoffToPointPopover" >
|
||||
<span>Take off</span>
|
||||
</Button>
|
||||
<div v-for="(cmdItem) in cmdList" :key="cmdItem.cmdKey" class="control-cmd-item">
|
||||
<Button :loading="cmdItem.loading" size="small" ghost @click="sendControlCmd(cmdItem, 0)">
|
||||
{{ cmdItem.operateText }}
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button size="small" ghost @click="openLivestreamAgora" >
|
||||
<span>Agora Live</span>
|
||||
</Button>
|
||||
<Button size="small" ghost @click="openLivestreamOthers" >
|
||||
<span>RTMP/GB28181 Live</span>
|
||||
</Button>
|
||||
</div>
|
||||
</DroneControlPopover>
|
||||
<Button :loading="cmdItem.loading" size="small" ghost @click="sendControlCmd(cmdItem, 0)">
|
||||
{{ cmdItem.operateText }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
@@ -250,9 +288,15 @@ import { usePayloadControl } from './use-payload-control'
|
||||
import { CameraMode, CameraType, CameraTypeOptions, ZoomCameraTypeOptions, CameraListItem } from '/@/types/live-stream'
|
||||
import { useDroneControlWsEvent } from './use-drone-control-ws-event'
|
||||
import { useDroneControlMqttEvent } from './use-drone-control-mqtt-event'
|
||||
import { postFlightAuth, LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight } from '/@/api/drone-control/drone'
|
||||
import {
|
||||
postFlightAuth, LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight, ERthMode,
|
||||
ECommanderModeLostAction, ECommanderFlightMode
|
||||
} from '/@/api/drone-control/drone'
|
||||
import { useDroneControl } from './use-drone-control'
|
||||
import { GimbalResetMode, GimbalResetModeOptions, LostControlActionInCommandFLightOptions, WaylineLostControlActionInCommandFlightOptions } from '/@/types/drone-control'
|
||||
import {
|
||||
GimbalResetMode, GimbalResetModeOptions, LostControlActionInCommandFLightOptions, WaylineLostControlActionInCommandFlightOptions,
|
||||
RthModeInCommandFlightOptions, CommanderModeLostActionInCommandFlightOptions, CommanderFlightModeInCommandFlightOptions
|
||||
} from '/@/types/drone-control'
|
||||
import DroneControlPopover from './DroneControlPopover.vue'
|
||||
import DroneControlInfoPanel from './DroneControlInfoPanel.vue'
|
||||
import { noDebugCmdList as baseCmdList, DeviceCmdItem, DeviceCmd } from '/@/types/device-cmd'
|
||||
@@ -269,8 +313,8 @@ const clientId = computed(() => {
|
||||
return store.state.clientId
|
||||
})
|
||||
|
||||
const initCmdList = baseCmdList.find(item => item.cmdKey === DeviceCmd.ReturnHome) as DeviceCmdItem
|
||||
const cmdItem = ref(initCmdList)
|
||||
const initCmdList = baseCmdList.map(cmdItem => Object.assign({}, cmdItem))
|
||||
const cmdList = ref(initCmdList)
|
||||
|
||||
const {
|
||||
sendDockControlCmd
|
||||
@@ -283,9 +327,11 @@ async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) {
|
||||
cmd: cmdItem.cmdKey,
|
||||
action: cmdItem.action
|
||||
}, false)
|
||||
if (result && flightController.value) {
|
||||
if (result) {
|
||||
message.success('Return home successful')
|
||||
exitFlightCOntrol()
|
||||
if (flightController.value) {
|
||||
exitFlightCOntrol()
|
||||
}
|
||||
} else {
|
||||
message.error('Failed to return home')
|
||||
}
|
||||
@@ -349,7 +395,11 @@ const takeoffToPointPopoverData = reactive({
|
||||
maxSpeed: MAX_SPEED,
|
||||
rthAltitude: null as null | number,
|
||||
rcLostAction: LostControlActionInCommandFLight.RETURN_HOME,
|
||||
exitWaylineWhenRcLost: WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION
|
||||
exitWaylineWhenRcLost: WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION,
|
||||
rthMode: ERthMode.SETTING,
|
||||
commanderModeLostAction: ECommanderModeLostAction.CONTINUE,
|
||||
commanderFlightMode: ECommanderFlightMode.SETTING,
|
||||
commanderFlightHeight: null as null | number,
|
||||
})
|
||||
|
||||
function onShowTakeoffToPointPopover () {
|
||||
@@ -361,6 +411,10 @@ function onShowTakeoffToPointPopover () {
|
||||
takeoffToPointPopoverData.rthAltitude = null
|
||||
takeoffToPointPopoverData.rcLostAction = LostControlActionInCommandFLight.RETURN_HOME
|
||||
takeoffToPointPopoverData.exitWaylineWhenRcLost = WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION
|
||||
takeoffToPointPopoverData.rthMode = ERthMode.SETTING
|
||||
takeoffToPointPopoverData.commanderModeLostAction = ECommanderModeLostAction.CONTINUE
|
||||
takeoffToPointPopoverData.commanderFlightMode = ECommanderFlightMode.SETTING
|
||||
takeoffToPointPopoverData.commanderFlightHeight = null
|
||||
}
|
||||
|
||||
async function onTakeoffToPointConfirm (confirm: boolean) {
|
||||
@@ -369,7 +423,8 @@ async function onTakeoffToPointConfirm (confirm: boolean) {
|
||||
!takeoffToPointPopoverData.latitude ||
|
||||
!takeoffToPointPopoverData.longitude ||
|
||||
!takeoffToPointPopoverData.securityTakeoffHeight ||
|
||||
!takeoffToPointPopoverData.rthAltitude) {
|
||||
!takeoffToPointPopoverData.rthAltitude ||
|
||||
!takeoffToPointPopoverData.commanderFlightHeight) {
|
||||
message.error('Input error')
|
||||
return
|
||||
}
|
||||
@@ -382,7 +437,11 @@ async function onTakeoffToPointConfirm (confirm: boolean) {
|
||||
rth_altitude: takeoffToPointPopoverData.rthAltitude,
|
||||
max_speed: takeoffToPointPopoverData.maxSpeed,
|
||||
rc_lost_action: takeoffToPointPopoverData.rcLostAction,
|
||||
exit_wayline_when_rc_lost: takeoffToPointPopoverData.exitWaylineWhenRcLost
|
||||
exit_wayline_when_rc_lost: takeoffToPointPopoverData.exitWaylineWhenRcLost,
|
||||
rth_mode: takeoffToPointPopoverData.rthMode,
|
||||
commander_mode_lost_action: takeoffToPointPopoverData.commanderModeLostAction,
|
||||
commander_flight_mode: takeoffToPointPopoverData.commanderFlightMode,
|
||||
commander_flight_height: takeoffToPointPopoverData.commanderFlightHeight,
|
||||
})
|
||||
} catch (error) {
|
||||
}
|
||||
@@ -672,6 +731,14 @@ function onShowCameraAimPopover () {
|
||||
cameraAimPopoverData.y = null
|
||||
}
|
||||
|
||||
function openLivestreamOthers () {
|
||||
store.commit('SET_LIVESTREAM_OTHERS_VISIBLE', true)
|
||||
}
|
||||
|
||||
function openLivestreamAgora () {
|
||||
store.commit('SET_LIVESTREAM_AGORA_VISIBLE', true)
|
||||
}
|
||||
|
||||
async function onCameraAimConfirm (confirm: boolean) {
|
||||
if (confirm) {
|
||||
if (cameraAimPopoverData.cameraType === null || cameraAimPopoverData.x === null || cameraAimPopoverData.y === null) {
|
||||
|
||||
@@ -45,8 +45,10 @@ export function useDockControl () {
|
||||
}
|
||||
|
||||
// 控制面板关闭
|
||||
async function onCloseControlPanel (sn: string) {
|
||||
await dockDebugOnOff(sn, false)
|
||||
async function onCloseControlPanel (sn: string, debugging: boolean) {
|
||||
if (debugging) {
|
||||
await dockDebugOnOff(sn, false)
|
||||
}
|
||||
setDockControlPanelVisible(false)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="mt20 flex-column flex-justify-start flex-align-center">
|
||||
<div class="flex-column flex-justify-start flex-align-center">
|
||||
<div id="player" style="width: 720px; height: 420px; border: 1px solid"></div>
|
||||
<p class="fz24">Live streaming source selection</p>
|
||||
<div class="flex-row flex-justify-center flex-align-center mt10">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex-column flex-justify-start flex-align-center mt20">
|
||||
<div class="flex-column flex-justify-start flex-align-center">
|
||||
<video
|
||||
:style="{ width: '720px', height: '480px' }"
|
||||
id="video-webrtc"
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
>Select Device</router-link>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="planBody.dock_sn" style="margin-top: -15px;">
|
||||
<div class="panel" style="padding-top: 5px;" @click="selectDock(dock)">
|
||||
<div class="panel" style="padding-top: 5px;">
|
||||
<div class="title">
|
||||
<a-tooltip :title="dock.nickname">
|
||||
<div class="pr10" style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">{{ dock.nickname }}</div>
|
||||
@@ -62,22 +62,64 @@
|
||||
</div>
|
||||
</a-form-item>
|
||||
<!-- 任务类型 -->
|
||||
<a-form-item label="Plan Timer" class="plan-timer-form-item" :labelCol="{span: 23}">
|
||||
<a-form-item label="Plan Timer" class="plan-timer-form-item">
|
||||
<div style="white-space: nowrap;">
|
||||
<a-radio-group v-model:value="planBody.task_type" button-style="solid">
|
||||
<a-radio-button v-for="type in TaskTypeOptions" :value="type.value" :key="type.value">{{ type.label }}</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<!-- 执行时间 -->
|
||||
<a-form-item label="Start Time" v-if="planBody.task_type === TaskType.Timed" name="select_execute_time" :labelCol="{span: 23}">
|
||||
<a-date-picker
|
||||
v-model:value="planBody.select_execute_time"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
show-time
|
||||
placeholder="Select Time"
|
||||
/>
|
||||
<!-- execute date -->
|
||||
<a-form-item label="Date" v-if="planBody.task_type === TaskType.Timed || planBody.task_type === TaskType.Condition" name="select_execute_date" :labelCol="{span: 23}">
|
||||
<a-range-picker
|
||||
v-model:value="planBody.select_execute_date"
|
||||
:disabledDate="(current: Moment) => current < moment().subtract(1, 'days')"
|
||||
format="YYYY-MM-DD"
|
||||
:placeholder="['Start Time', 'End Time']"
|
||||
style="width: 100%;"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- execute time -->
|
||||
<a-form-item label="Time" v-if="planBody.task_type === TaskType.Timed || planBody.task_type === TaskType.Condition"
|
||||
name="select_execute_time" ref="select_execute_time" :labelCol="{span: 23}" :autoLink="false">
|
||||
<div class="mb10 flex-row flex-align-center flex-justify-around" v-for="n in planBody.select_time_number" :key="n">
|
||||
<a-time-picker
|
||||
v-model:value="planBody.select_time[n - 1][0]"
|
||||
format="HH:mm:ss"
|
||||
show-time
|
||||
placeholder="Start Time"
|
||||
:style="planBody.task_type === TaskType.Condition ? 'width: 40%' : 'width: 82%'"
|
||||
@change="() => $refs.select_execute_time.onFieldChange()"
|
||||
/>
|
||||
<template v-if="planBody.task_type === TaskType.Condition">
|
||||
<div><span style="color: white;">-</span></div>
|
||||
<a-time-picker
|
||||
v-model:value="planBody.select_time[n - 1][1]"
|
||||
format="HH:mm:ss"
|
||||
show-time
|
||||
placeholder="End Time"
|
||||
style="width: 40%;"
|
||||
/>
|
||||
</template>
|
||||
<div class="ml5" style="font-size:18px">
|
||||
<PlusCircleOutlined class="mr5" style="color: #1890ff" @click="addTime"/>
|
||||
<MinusCircleOutlined :style="planBody.select_time_number === 1 ? 'color: gray' : 'color: red;'" @click="removeTime"/>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<template v-if="planBody.task_type === TaskType.Condition">
|
||||
<!-- battery capacity -->
|
||||
<a-form-item label="Start task when battery level reaches" :labelCol="{span: 23}" name="min_battery_capacity">
|
||||
<a-input-number class="width-100" v-model:value="planBody.min_battery_capacity" :min="50" :max="100"
|
||||
:formatter="(value: number) => `${value}%`" :parser="(value: string) => value.replace('%', '')">
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
<!-- storage capacity -->
|
||||
<a-form-item label="Start task when storage level reaches (MB)" :labelCol="{span: 23}" name="storage_capacity">
|
||||
<a-input-number v-model:value="planBody.min_storage_capacity" class="width-100">
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<!-- RTH Altitude Relative to Dock -->
|
||||
<a-form-item label="RTH Altitude Relative to Dock (m)" :labelCol="{span: 23}" name="rth_altitude">
|
||||
<a-input-number v-model:value="planBody.rth_altitude" :min="20" :max="1500" class="width-100" required>
|
||||
@@ -145,12 +187,16 @@ const disabled = ref(false)
|
||||
const routeName = ref('')
|
||||
const planBody = reactive({
|
||||
name: '',
|
||||
file_id: computed(() => store.state.waylineInfo.id),
|
||||
dock_sn: computed(() => store.state.dockInfo.device_sn),
|
||||
file_id: computed(() => store.state?.waylineInfo.id),
|
||||
dock_sn: computed(() => store.state?.dockInfo.device_sn),
|
||||
task_type: TaskType.Immediate,
|
||||
select_execute_time: undefined as Moment| undefined,
|
||||
select_execute_date: [moment(), moment()] as Moment[],
|
||||
select_time_number: 1,
|
||||
select_time: [[]] as Moment[][],
|
||||
rth_altitude: '',
|
||||
out_of_control_action: OutOfControlAction.ReturnToHome,
|
||||
min_battery_capacity: 90 as number,
|
||||
min_storage_capacity: undefined as number | undefined,
|
||||
})
|
||||
|
||||
const drawerVisible = ref(false)
|
||||
@@ -158,16 +204,35 @@ const valueRef = ref()
|
||||
const rules = {
|
||||
name: [
|
||||
{ required: true, message: 'Please enter plan name.' },
|
||||
{ max: 20, message: 'Length should be 1 to 20', trigger: 'blur' }
|
||||
{ max: 20, message: 'Length should be 1 to 20' }
|
||||
],
|
||||
file_id: [{ required: true, message: 'Select Route' }],
|
||||
dock_sn: [{ required: true, message: 'Select Device' }],
|
||||
select_execute_time: [{ required: true, message: 'Select start time' }],
|
||||
select_execute_time: [{
|
||||
validator: async (rule: RuleObject, value: Moment[]) => {
|
||||
validEndTime()
|
||||
validStartTime()
|
||||
if (planBody.select_time.length < planBody.select_time_number) {
|
||||
throw new Error('Select time')
|
||||
}
|
||||
validOverlapped()
|
||||
}
|
||||
}],
|
||||
select_execute_date: [{ required: true, message: 'Select date' }],
|
||||
rth_altitude: [
|
||||
{
|
||||
validator: async (rule: RuleObject, value: string) => {
|
||||
if (!/^[0-9]{1,}$/.test(value)) {
|
||||
throw new Error('RTH Altitude Relative Require number')
|
||||
throw new Error('RTH Altitude Require number')
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
min_battery_capacity: [
|
||||
{
|
||||
validator: async (rule: RuleObject, value: any) => {
|
||||
if (TaskType.Condition === planBody.task_type && !value) {
|
||||
throw new Error('Please enter battery capacity')
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -175,19 +240,61 @@ const rules = {
|
||||
out_of_control_action: [{ required: true, message: 'Select Lost Action' }],
|
||||
}
|
||||
|
||||
function validStartTime (): Error | void {
|
||||
for (let i = 0; i < planBody.select_time.length; i++) {
|
||||
if (!planBody.select_time[i][0]) {
|
||||
throw new Error('Select start time')
|
||||
}
|
||||
}
|
||||
}
|
||||
function validEndTime (): Error | void {
|
||||
if (TaskType.Condition !== planBody.task_type) return
|
||||
for (let i = 0; i < planBody.select_time.length; i++) {
|
||||
if (!planBody.select_time[i][1]) {
|
||||
throw new Error('Select end time')
|
||||
}
|
||||
if (planBody.select_time[i][0] && planBody.select_time[i][1].isSameOrBefore(planBody.select_time[i][0])) {
|
||||
throw new Error('End time should be later than start time')
|
||||
}
|
||||
}
|
||||
}
|
||||
function validOverlapped (): Error | void {
|
||||
if (TaskType.Condition !== planBody.task_type) return
|
||||
const arr = planBody.select_time.slice()
|
||||
arr.sort((a, b) => a[0].unix() - b[0].unix())
|
||||
arr.forEach((v, i, arr) => {
|
||||
if (i > 0 && v[0] < arr[i - 1][1]) {
|
||||
throw new Error('Overlapping time periods.')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit () {
|
||||
console.info(dock, '12131231')
|
||||
valueRef.value.validate().then(() => {
|
||||
disabled.value = true
|
||||
const createPlanBody = { ...planBody } as unknown as CreatePlan
|
||||
if (planBody.select_execute_time) {
|
||||
createPlanBody.task_days = [moment(planBody.select_execute_time).unix()]
|
||||
createPlanBody.task_periods = [createPlanBody.task_days]
|
||||
if (planBody.select_execute_date.length === 2) {
|
||||
createPlanBody.task_days = []
|
||||
for (let i = planBody.select_execute_date[0]; i.isSameOrBefore(planBody.select_execute_date[1]); i.add(1, 'days')) {
|
||||
createPlanBody.task_days.push(i.unix())
|
||||
}
|
||||
}
|
||||
createPlanBody.task_periods = []
|
||||
if (TaskType.Immediate !== planBody.task_type) {
|
||||
for (let i = 0; i < planBody.select_time.length; i++) {
|
||||
const result = []
|
||||
result.push(planBody.select_time[i][0].unix())
|
||||
if (TaskType.Condition === planBody.task_type) {
|
||||
result.push(planBody.select_time[i][1].unix())
|
||||
}
|
||||
createPlanBody.task_periods.push(result)
|
||||
}
|
||||
}
|
||||
createPlanBody.rth_altitude = Number(createPlanBody.rth_altitude)
|
||||
if (wayline.value && wayline.value.template_types && wayline.value.template_types.length > 0) {
|
||||
createPlanBody.wayline_type = wayline.value.template_types[0]
|
||||
}
|
||||
// console.log('planBody', createPlanBody)
|
||||
createPlan(workspaceId, createPlanBody)
|
||||
.then(res => {
|
||||
disabled.value = false
|
||||
@@ -217,6 +324,18 @@ function selectDevice () {
|
||||
drawerVisible.value = true
|
||||
routeName.value = 'DockPanel'
|
||||
}
|
||||
|
||||
function addTime () {
|
||||
valueRef.value.validateFields(['select_execute_time']).then(() => {
|
||||
planBody.select_time_number++
|
||||
planBody.select_time.push([])
|
||||
})
|
||||
}
|
||||
function removeTime () {
|
||||
if (planBody.select_time_number === 1) return
|
||||
planBody.select_time_number--
|
||||
planBody.select_time.splice(planBody.select_time_number)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -266,7 +385,7 @@ function selectDevice () {
|
||||
.ant-radio-button-wrapper{
|
||||
background-color: #232323;
|
||||
color: #fff;
|
||||
width: 80%;
|
||||
width: 33%;
|
||||
text-align: center;
|
||||
&.ant-radio-button-wrapper-checked{
|
||||
background-color: #1890ff;
|
||||
|
||||
@@ -11,8 +11,8 @@ export const MapElementDefaultColor = MapElementColor.Default
|
||||
|
||||
export enum MapDoodleColor {
|
||||
PinColor = '#2D8CF0',
|
||||
PolylineColor = '#3366FF',
|
||||
PolygonColor = '#FF33FF'
|
||||
PolylineColor = '#2D8CF0',
|
||||
PolygonColor = '#2D8CF0'
|
||||
}
|
||||
|
||||
export enum MapElementEnum {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { nextTick, App } from 'vue'
|
||||
|
||||
export default function useDragWindowDirective (app: App): void {
|
||||
app.directive('drag-window', async (el) => {
|
||||
await nextTick()
|
||||
|
||||
const modal = el
|
||||
const header = el.getElementsByClassName('drag-title')[0]
|
||||
let left = 0
|
||||
let top = 0
|
||||
header.style.cursor = 'move'
|
||||
top = top || modal.offsetTop
|
||||
|
||||
header.onpointerdown = (e: { clientX: number; clientY: number; pointerId: number }) => {
|
||||
const startX = e.clientX
|
||||
const startY = e.clientY
|
||||
header.left = header.offsetLeft
|
||||
header.top = header.offsetTop
|
||||
header.setPointerCapture(e.pointerId)
|
||||
|
||||
el.onpointermove = (event: { clientX: number; clientY: number }) => {
|
||||
const endX = event.clientX
|
||||
const endY = event.clientY
|
||||
modal.left = header.left + (endX - startX) + left
|
||||
modal.top = header.top + (endY - startY) + top
|
||||
modal.style.left = modal.left + 'px'
|
||||
modal.style.top = modal.top + 'px'
|
||||
}
|
||||
el.onpointerup = () => {
|
||||
left = modal.left || 0
|
||||
top = modal.top || 0
|
||||
el.onpointermove = null
|
||||
el.onpointerup = null
|
||||
header.releasePointerCapture(e.pointerId)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { App } from 'vue'
|
||||
import useDragWindowDirective from './drag-window'
|
||||
|
||||
export function useDirectives (app: App): void {
|
||||
useDragWindowDirective(app)
|
||||
}
|
||||
@@ -78,9 +78,9 @@ export function useGMapCover () {
|
||||
AddOverlayGroup(polyline)
|
||||
}
|
||||
|
||||
function initPolygon (name: string, coordinates:GeojsonCoordinate[], color?:string, data?:{}) {
|
||||
function initPolygon (name: string, coordinates:GeojsonCoordinate[][], color?:string, data?:{}) {
|
||||
const path = [] as GeojsonCoordinate[]
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinates[0].forEach(coordinate => {
|
||||
path.push(new AMap.LngLat(coordinate[0], coordinate[1]))
|
||||
})
|
||||
// console.log('Polygon', path)
|
||||
@@ -141,12 +141,43 @@ export function useGMapCover () {
|
||||
}
|
||||
}
|
||||
|
||||
function updatePolylineElement (id:string, name: string, coordinates:GeojsonCoordinate[], color?:string) {
|
||||
const element = getElementFromMap(id) as any
|
||||
if (element) {
|
||||
const options = element.getOptions()
|
||||
options.strokeColor = color || normalColor
|
||||
element.setOptions(options)
|
||||
} else {
|
||||
initPolyline(name, coordinates, color, {
|
||||
id: id,
|
||||
name: name
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function updatePolygonElement (id:string, name: string, coordinates:GeojsonCoordinate[][], color?:string) {
|
||||
const element = getElementFromMap(id) as any
|
||||
if (element) {
|
||||
const options = element.getOptions()
|
||||
options.fillColor = color || normalColor
|
||||
options.strokeColor = color || normalColor
|
||||
element.setOptions(options)
|
||||
} else {
|
||||
initPolygon(name, coordinates, color, {
|
||||
id: id,
|
||||
name: name
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init2DPin,
|
||||
initPolyline,
|
||||
initPolygon,
|
||||
removeCoverFromMap,
|
||||
getElementFromMap,
|
||||
updatePinElement
|
||||
updatePinElement,
|
||||
updatePolylineElement,
|
||||
updatePolygonElement
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,14 @@ import { CommonComponents } from './use-common-components'
|
||||
import 'virtual:svg-icons-register'
|
||||
import store, { storeKey } from './store'
|
||||
import { createInstance } from '/@/root'
|
||||
import { useDirectives } from './directives'
|
||||
|
||||
import '/@/styles/index.scss'
|
||||
const app = createInstance(App)
|
||||
|
||||
app.use(store, storeKey)
|
||||
app.use(router)
|
||||
app.use(CommonComponents)
|
||||
app.use(antComponents)
|
||||
app.use(useDirectives)
|
||||
app.mount('#demo-app')
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<RightOutlined style="float: right; margin-top: 5px; color: #8894a0" />
|
||||
</div>
|
||||
<div style="height: 50%;">
|
||||
<CloudSyncOutlined v-if="state === EStatusValue.CONNECTED" style="color: #75c5f6" />
|
||||
<CloudSyncOutlined v-if="thingState === EStatusValue.CONNECTED" style="color: #75c5f6" />
|
||||
<SyncOutlined spin v-else/>
|
||||
<span style="color: #737373; margin-left: 3px;">{{ state }}</span>
|
||||
<span style="color: #737373; margin-left: 3px;">{{ thingState }}</span>
|
||||
</div>
|
||||
<a-drawer placement="right" v-model:visible="drawerVisible" width="340px">
|
||||
<div class="mb10 flex-row flex-justify-center flex-align-center">
|
||||
@@ -135,7 +135,6 @@ import { useConnectWebSocket } from '/@/hooks/use-connect-websocket'
|
||||
|
||||
const root = getRoot()
|
||||
const gatewayState = ref<boolean>(localStorage.getItem(ELocalStorageKey.GatewayOnline) === 'true')
|
||||
const state = ref(EStatusValue.DISCONNECT)
|
||||
const thingState = ref(EStatusValue.DISCONNECT)
|
||||
const apiState = ref(EStatusValue.DISCONNECT)
|
||||
const liveState = ref(EStatusValue.DISCONNECT)
|
||||
@@ -157,7 +156,7 @@ interface DeviceInfoData {
|
||||
}
|
||||
const device = reactive<DeviceInfoData>({
|
||||
data: {
|
||||
sn: EStatusValue.DISCONNECT,
|
||||
sn: '',
|
||||
online_status: false,
|
||||
device_callsign: '',
|
||||
user_id: '',
|
||||
@@ -218,9 +217,7 @@ const messageHandler = async (payload: any) => {
|
||||
case EBizCode.DeviceOnline: {
|
||||
console.info('online: ', payload)
|
||||
if (payload.data.sn === device.data.gateway_sn) {
|
||||
gatewayState.value = true
|
||||
localStorage.setItem(ELocalStorageKey.GatewayOnline, gatewayState.value.toString())
|
||||
state.value = gatewayState.value && thingState.value === EStatusValue.CONNECTED ? EStatusValue.CONNECTED : EStatusValue.DISCONNECT
|
||||
break
|
||||
}
|
||||
if (payload.data.gateway_sn === device.data.gateway_sn) {
|
||||
@@ -441,7 +438,6 @@ function refreshStatus () {
|
||||
tsaState.value = apiPilot.isComponentLoaded(EComponentName.Tsa) ? EStatusValue.CONNECTED : EStatusValue.DISCONNECT
|
||||
mediaState.value = apiPilot.isComponentLoaded(EComponentName.Media) ? EStatusValue.CONNECTED : EStatusValue.DISCONNECT
|
||||
waylineState.value = apiPilot.isComponentLoaded(EComponentName.Mission) ? EStatusValue.CONNECTED : EStatusValue.DISCONNECT
|
||||
state.value = thingState.value === EStatusValue.CONNECTED && gatewayState.value ? EStatusValue.CONNECTED : EStatusValue.DISCONNECT
|
||||
}
|
||||
|
||||
function moduleInstall (m: any) {
|
||||
|
||||
@@ -54,7 +54,26 @@
|
||||
<div class="width-100" style="margin-top: -10px;">
|
||||
<div class="ml10" style="width: 97%;">
|
||||
<span class="fz16">Param: </span>
|
||||
<span v-if="liveStreamStatus.type === ELiveTypeValue.Agora" style="word-break: break-all; color: #75c5f6;">{{ agoraParam }}</span>
|
||||
<span v-if="liveStreamStatus.type === ELiveTypeValue.Agora" style="word-break: break-all; color: #75c5f6;">
|
||||
<div class="flex-col flex-justify-center flex-align-center">
|
||||
<div>
|
||||
<span class="ml10">Token:</span>
|
||||
<a-input
|
||||
class="ml10"
|
||||
v-model:value="agoraParam.token"
|
||||
placeholder="Token"
|
||||
></a-input>
|
||||
</div>
|
||||
<div>
|
||||
<span class="ml10">Channel:</span>
|
||||
<a-input
|
||||
class="ml10"
|
||||
v-model:value="agoraParam.channelId"
|
||||
placeholder="Channel"
|
||||
></a-input>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<span v-else-if="liveStreamStatus.type === ELiveTypeValue.RTMP" style="word-break: break-all; color: #75c5f6;">{{ rtmpParam }}</span>
|
||||
<span v-else-if="liveStreamStatus.type === ELiveTypeValue.RTSP" style="word-break: break-all; color: #75c5f6;">{{ rtspParam }}</span>
|
||||
<span v-else-if="liveStreamStatus.type === ELiveTypeValue.GB28181" style="word-break: break-all; color: #75c5f6;">{{ gb28181Param }}</span>
|
||||
@@ -154,11 +173,11 @@ const liveTypeList = [
|
||||
label: ELiveTypeName.GB28181
|
||||
}
|
||||
]
|
||||
const agoraParam = {
|
||||
const agoraParam = reactive({
|
||||
uid: '2892130292',
|
||||
token: config.agoraToken,
|
||||
channelId: config.agoraChannel
|
||||
}
|
||||
})
|
||||
const rtmpParam = {
|
||||
url: config.rtmpURL + new Date().getTime()
|
||||
}
|
||||
@@ -174,7 +193,7 @@ const gb28181Param: GB28181Param = {
|
||||
agentId: CURRENT_CONFIG.gbAgentId,
|
||||
password: CURRENT_CONFIG.gbPassword,
|
||||
agentPort: CURRENT_CONFIG.gbAgentPort,
|
||||
agentChannel: CURRENT_CONFIG.gbAgentChannel
|
||||
agentChannel: CURRENT_CONFIG.gbAgentChannel,
|
||||
}
|
||||
|
||||
const playVisiable = ref(false)
|
||||
@@ -253,6 +272,7 @@ const onPublishModeSelect = (val: string) => {
|
||||
apiPilot.setVideoPublishType(publishModeSelected.value)
|
||||
}
|
||||
const onPlay = () => {
|
||||
console.info(JSON.stringify(agoraParam))
|
||||
if (!publishModeSelected.value) {
|
||||
message.warn('Please select publish mode!')
|
||||
return
|
||||
|
||||
@@ -171,7 +171,6 @@ function updateMapElement (
|
||||
const geoType = element.resource?.content.geometry.type
|
||||
const id = element.id
|
||||
const type = element.resource?.type as number
|
||||
|
||||
if (MapElementEnum.PIN === type) {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates as GeojsonCoordinate
|
||||
@@ -179,17 +178,11 @@ function updateMapElement (
|
||||
} else if (MapElementEnum.LINE === type && geoType === 'LineString') {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates as GeojsonCoordinate[]
|
||||
useGMapCoverHook.initPolyline(name, coordinates, color, {
|
||||
id: id,
|
||||
name: name
|
||||
})
|
||||
useGMapCoverHook.updatePolylineElement(id, name, coordinates, color)
|
||||
} else if (MapElementEnum.POLY === type && geoType === 'Polygon') {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates[0] as GeojsonCoordinate[]
|
||||
useGMapCoverHook.initPolygon(name, coordinates, color, {
|
||||
id: id,
|
||||
name: name
|
||||
})
|
||||
.coordinates as GeojsonCoordinate[][]
|
||||
useGMapCoverHook.updatePolygonElement(id, name, coordinates, color)
|
||||
}
|
||||
}
|
||||
function checkLayer (keys: string[]) {
|
||||
@@ -235,10 +228,12 @@ function setBaseInfo () {
|
||||
layerState.layerName = layer.name
|
||||
layerState.layerId = layer.id
|
||||
layerState.color = layer.resource?.content.properties.color
|
||||
let coordinate: GeojsonCoordinate
|
||||
switch (geoType) {
|
||||
case GeoType.Point:
|
||||
layerState.longitude = layer.resource?.content.geometry.coordinates[0]
|
||||
layerState.latitude = layer.resource?.content.geometry.coordinates[1]
|
||||
coordinate = gcj02towgs84(layer.resource?.content.geometry.coordinates[0], layer.resource?.content.geometry.coordinates[1]) as GeojsonCoordinate
|
||||
layerState.longitude = coordinate[0]
|
||||
layerState.latitude = coordinate[1]
|
||||
break
|
||||
case GeoType.LineString:
|
||||
break
|
||||
@@ -250,7 +245,7 @@ function setBaseInfo () {
|
||||
onMounted(() => {
|
||||
const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement
|
||||
const parent = element?.parentNode as HTMLDivElement
|
||||
scorllHeight.value = parent.clientHeight - parent.firstElementChild!.clientHeight
|
||||
scorllHeight.value = parent?.clientHeight - parent.firstElementChild!.clientHeight
|
||||
getAllElement()
|
||||
})
|
||||
function closeDrawer () {
|
||||
@@ -356,39 +351,39 @@ function updateCoordinates (transformType: string, element: LayerResource) {
|
||||
) as GeojsonCoordinate
|
||||
element.resource.content.geometry.coordinates = transResult
|
||||
}
|
||||
} else if (MapElementEnum.LINE === type && geoType === 'LineString') {
|
||||
} else if (MapElementEnum.LINE === type) {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates as GeojsonCoordinate[]
|
||||
if (transformType === 'wgs84-gcj02') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = wgs84togcj02(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = wgs84togcj02(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
})
|
||||
} else if (transformType === 'gcj02-wgs84') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = gcj02towgs84(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = gcj02towgs84(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
})
|
||||
}
|
||||
element.resource.content.geometry.coordinates = coordinates
|
||||
} else if (MapElementEnum.LINE === type && geoType === 'Polygon') {
|
||||
} else if (MapElementEnum.POLY === type) {
|
||||
const coordinates = element.resource?.content.geometry
|
||||
.coordinates[0] as GeojsonCoordinate[]
|
||||
|
||||
if (transformType === 'wgs84-gcj02') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = wgs84togcj02(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = wgs84togcj02(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
})
|
||||
} else if (transformType === 'gcj02-wgs84') {
|
||||
coordinates.forEach(coordinate => {
|
||||
coordinate = gcj02towgs84(
|
||||
coordinates.forEach((coordinate, i, arr) => {
|
||||
arr[i] = gcj02towgs84(
|
||||
coordinate[0],
|
||||
coordinate[1]
|
||||
) as GeojsonCoordinate
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="live" v-if="showLive">
|
||||
<div class="live" v-if="showLive" v-drag-window>
|
||||
<div style="height: 40px; width: 100%" class="drag-title"></div>
|
||||
<a style="position: absolute; right: 10px; top: 10px; font-size: 16px; color: white;" @click="() => root.$router.push('/' + ERouterName.LIVESTREAM)"><CloseOutlined /></a>
|
||||
<router-view :name="routeName" />
|
||||
</div>
|
||||
@@ -74,14 +75,13 @@ onMounted(() => {
|
||||
.live {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 50%;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin: auto;
|
||||
transform: translate(-50%, -50%);
|
||||
left: 0;
|
||||
top: 10px;
|
||||
margin-left: 345px;
|
||||
|
||||
text-align: center;
|
||||
width: 800px;
|
||||
height: 700px;
|
||||
height: 720px;
|
||||
background: #232323;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -203,7 +203,7 @@ import { EHmsLevel } from '/@/types/enums'
|
||||
const store = useMyStore()
|
||||
const username = ref(localStorage.getItem(ELocalStorageKey.Username))
|
||||
const workspaceId = ref(localStorage.getItem(ELocalStorageKey.WorkspaceId)!)
|
||||
const osdVisible = ref({} as OSDVisible)
|
||||
const osdVisible = computed(() => store.state.osdVisible)
|
||||
const hmsVisible = new Map<string, boolean>()
|
||||
const scorllHeight = ref()
|
||||
|
||||
@@ -344,6 +344,15 @@ function readHms (visiable: boolean, sn: string) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function openLivestreamOthers () {
|
||||
store.commit('SET_LIVESTREAM_OTHERS_VISIBLE', true)
|
||||
}
|
||||
|
||||
function openLivestreamAgora () {
|
||||
store.commit('SET_LIVESTREAM_AGORA_VISIBLE', true)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -47,6 +47,10 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('/@/pages/page-web/projects/workspace.vue'),
|
||||
redirect: '/' + ERouterName.TSA,
|
||||
children: [
|
||||
{
|
||||
path: '/' + ERouterName.TSA,
|
||||
component: () => import('/@/pages/page-web/projects/tsa.vue')
|
||||
},
|
||||
{
|
||||
path: '/' + ERouterName.LIVESTREAM,
|
||||
name: ERouterName.LIVESTREAM,
|
||||
@@ -62,10 +66,6 @@ const routes: Array<RouteRecordRaw> = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/' + ERouterName.TSA,
|
||||
component: () => import('/@/pages/page-web/projects/tsa.vue')
|
||||
},
|
||||
{
|
||||
path: '/' + ERouterName.LAYER,
|
||||
name: ERouterName.LAYER,
|
||||
|
||||
@@ -32,6 +32,8 @@ const initStateFunc = () => ({
|
||||
[key:string]:string
|
||||
},
|
||||
drawVisible: false,
|
||||
livestreamOthersVisible: false,
|
||||
livestreamAgoraVisible: false,
|
||||
coverList: [
|
||||
|
||||
] as any,
|
||||
@@ -124,7 +126,7 @@ const mutations: MutationTree<RootStateType> = {
|
||||
dock.basic_osd = info.host
|
||||
return
|
||||
}
|
||||
if (info.host.sdr) {
|
||||
if (info.host.wireless_link) {
|
||||
dock.link_osd = info.host
|
||||
return
|
||||
}
|
||||
@@ -135,6 +137,12 @@ const mutations: MutationTree<RootStateType> = {
|
||||
SET_DRAW_VISIBLE_INFO (state, bool) {
|
||||
state.drawVisible = bool
|
||||
},
|
||||
SET_LIVESTREAM_OTHERS_VISIBLE (state, bool) {
|
||||
state.livestreamOthersVisible = bool
|
||||
},
|
||||
SET_LIVESTREAM_AGORA_VISIBLE (state, bool) {
|
||||
state.livestreamAgoraVisible = bool
|
||||
},
|
||||
SET_MAP_ELEMENT_CREATE (state, info) {
|
||||
state.wsEvent.mapElementCreat = info
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ export enum DeviceCmd {
|
||||
SupplementLightOpen = 'supplement_light_open', // 打开补光灯
|
||||
SupplementLightClose = 'supplement_light_close', // 关闭补光灯
|
||||
ReturnHome = 'return_home', // 一键返航
|
||||
ReturnHomeCancel = 'return_home_cancel', // 取消返航
|
||||
// 复杂指令
|
||||
DeviceReboot = 'device_reboot', // 机场重启
|
||||
DroneOpen = 'drone_open', // 飞行器开机
|
||||
@@ -48,6 +49,14 @@ export const noDebugCmdList: DeviceCmdItem[] = [
|
||||
func: 'returnHome',
|
||||
loading: false,
|
||||
},
|
||||
{
|
||||
label: 'Return Home Cancel',
|
||||
status: '--',
|
||||
operateText: 'Return Home Cancel',
|
||||
cmdKey: DeviceCmd.ReturnHomeCancel,
|
||||
func: 'returnHomeCancel',
|
||||
loading: false,
|
||||
}
|
||||
]
|
||||
|
||||
// 机场指令
|
||||
|
||||
@@ -319,7 +319,7 @@ export interface DockBasicOsd {
|
||||
state: number,
|
||||
capacity_percent: number,
|
||||
},
|
||||
drone_in_dock: DroneInDockEnum,
|
||||
drone_in_dock: boolean,
|
||||
rainfall: RainfallEnum,
|
||||
wind_speed: number,
|
||||
environment_temperature: number,
|
||||
@@ -379,7 +379,7 @@ export interface DockLinkOsd {
|
||||
media_file_detail?: {
|
||||
remain_upload: number
|
||||
},
|
||||
sdr: {
|
||||
sdr?: {
|
||||
up_quality: string,
|
||||
down_quality: string,
|
||||
frequency_band: number,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ControlSource } from './device'
|
||||
import { LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight } from '/@/api/drone-control/drone'
|
||||
import { ECommanderModeLostAction, ERthMode, LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight } from '/@/api/drone-control/drone'
|
||||
|
||||
export enum ControlSourceChangeType {
|
||||
Flight = 1,
|
||||
@@ -52,6 +52,21 @@ export const LostControlActionInCommandFLightOptions = [
|
||||
{ label: 'Landing', value: LostControlActionInCommandFLight.Land }
|
||||
]
|
||||
|
||||
export const RthModeInCommandFlightOptions = [
|
||||
{ label: 'Smart Height', value: ERthMode.SMART },
|
||||
{ label: 'Setting Height', value: ERthMode.SETTING }
|
||||
]
|
||||
|
||||
export const CommanderModeLostActionInCommandFlightOptions = [
|
||||
{ label: 'Continue', value: ECommanderModeLostAction.CONTINUE },
|
||||
{ label: 'Execute Lost Action', value: ECommanderModeLostAction.EXEC_LOST_ACTION }
|
||||
]
|
||||
|
||||
export const CommanderFlightModeInCommandFlightOptions = [
|
||||
{ label: 'Smart Height', value: ERthMode.SMART },
|
||||
{ label: 'Setting Height', value: ERthMode.SETTING }
|
||||
]
|
||||
|
||||
// 云台重置模式
|
||||
export enum GimbalResetMode {
|
||||
Recenter = 0,
|
||||
|
||||
@@ -4,16 +4,19 @@ import { commonColor } from '/@/utils/color'
|
||||
export enum TaskType {
|
||||
Immediate = 0, // 立即执行
|
||||
Timed = 1, // 单次定时任务
|
||||
Condition = 2,
|
||||
}
|
||||
|
||||
export const TaskTypeMap = {
|
||||
[TaskType.Immediate]: 'Immediate',
|
||||
[TaskType.Timed]: 'Timed',
|
||||
[TaskType.Condition]: 'Continuous',
|
||||
}
|
||||
|
||||
export const TaskTypeOptions = [
|
||||
{ value: TaskType.Immediate, label: TaskTypeMap[TaskType.Immediate] },
|
||||
{ value: TaskType.Timed, label: TaskTypeMap[TaskType.Timed] },
|
||||
{ value: TaskType.Condition, label: TaskTypeMap[TaskType.Condition] },
|
||||
]
|
||||
|
||||
// 失控动作
|
||||
|
||||
+3
-2
@@ -24,6 +24,7 @@
|
||||
"src/**/*.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue"
|
||||
, "src/vendors/coordtransform.js" ]
|
||||
"src/**/*.vue",
|
||||
"src/vendors/coordtransform.js"
|
||||
]
|
||||
}
|
||||
Referência em uma Nova Issue
Bloquear um usuário