import { DRC_METHOD } from '@/const/drc.js'
|
import { ElMessage } from 'element-plus'
|
import { postPayloadCommands, ptzControlApi } from '@/api/payload'
|
import _, { throttle } from 'lodash'
|
import EventBus from '@/utils/eventBus'
|
import store from '@/store/'
|
let myInterval
|
|
export const KeyCode = {
|
KEY_W: 'KeyW',
|
KEY_A: 'KeyA',
|
KEY_S: 'KeyS',
|
KEY_D: 'KeyD',
|
KEY_Q: 'KeyQ',
|
KEY_E: 'KeyE',
|
KEY_J: 'KeyJ',
|
KEY_K: 'KeyK',
|
KEY_L: 'KeyL',
|
KEY_X: 'KeyX',
|
KEY_Z: 'KeyZ',
|
KEY_C: 'KeyC',
|
KEY_I: 'KeyI',
|
KEY_O: 'KeyO',
|
ARROW_UP: 'ArrowUp',
|
ARROW_DOWN: 'ArrowDown',
|
ARROW_LEFT: 'ArrowLeft',
|
ARROW_RIGHT: 'ArrowRight',
|
NUMPAD_SUBTRACT: 'NumpadSubtract',
|
NUMPAD_ADD: 'NumpadAdd',
|
// 提升速度
|
KEY_EQUAL: 'Equal',
|
KEY_MINUS: 'Minus',
|
// 录音
|
KEY_N: 'KeyN',
|
KEY_M: 'KeyM',
|
}
|
|
export function useManualControl(mqttHooks,deviceTopicInfo,paramsRef,isManualControl,modelCode,activeBtnList) {
|
let activeCodeKey = null
|
let genPortOne = true //是一代机场
|
let seq = 0
|
let downTime = null; // 按键按下时间
|
|
const keysPressed = [
|
{key: 'KeyQ', value: false},
|
{key: 'KeyW', value: false},
|
{key: 'KeyE', value: false},
|
{key: 'KeyA', value: false},
|
{key: 'KeyS', value: false},
|
{key: 'KeyD', value: false},
|
{key: 'KeyC', value: false},
|
{key: 'KeyZ', value: false},
|
{key: 'ArrowUp', value: false},
|
{key: 'ArrowDown', value: false},
|
{key: 'ArrowLeft', value: false},
|
{key: 'ArrowRight', value: false},
|
]
|
|
// QE按键额外处理
|
function qKeyEKeyHandle() {
|
let ratio = (Date.now()-downTime) / 4000
|
if (ratio > 1) ratio = 1;
|
if (ratio < 0.1) ratio = 0.1;
|
const W_SPEED = (genPortOne ? 90 : 600) * ratio
|
let obj
|
if (activeCodeKey === 'KeyQ'){
|
obj = { yaw: 1024-W_SPEED }
|
if (genPortOne) {obj = {w: -W_SPEED}}
|
}else{
|
obj = { yaw: 1024+W_SPEED }
|
if (genPortOne) {obj = {w: W_SPEED}}
|
}
|
return obj
|
}
|
|
// 云台参数处理,最大20°
|
function ptzKeyHandle() {
|
let ratio = (Date.now()-downTime) / 4000
|
if (ratio > 1) ratio = 1;
|
if (ratio < 0.1) ratio = 0.1;
|
return 20 * ratio
|
}
|
|
// 变焦倍数处理,最大5倍
|
function getZoomFactor() {
|
let ratio = (Date.now()-downTime) / 4000
|
if (ratio > 1) ratio = 1;
|
if (ratio < 0.1) ratio = 0.2;
|
return 5 * ratio
|
}
|
|
// 处理无人机控制指令的发布逻辑
|
function handlePublish(params) {
|
const body = {
|
method: genPortOne ? DRC_METHOD.DRONE_CONTROL : DRC_METHOD.DRONE_CONTROL2,
|
data: params,
|
}
|
handleClearInterval()
|
myInterval = setInterval(() => {
|
body.data.seq = seq++
|
seq++
|
// q,e额外处理
|
if (['KeyQ', 'KeyE'].includes(activeCodeKey)){
|
body.data = qKeyEKeyHandle()
|
}
|
window.console.log('keyCode>>>>', activeCodeKey, body)
|
mqttHooks?.publishMqtt(deviceTopicInfo.pubTopic, body, { qos: 0 })
|
}, 50)
|
}
|
|
let downKeyCode
|
// 案件按下逻辑
|
function handleKeyup(keyCode) {
|
console.log(keyCode,'keyCodekeyCode')
|
const droneControl = [3, 16, 17].includes(modelCode.value)
|
if (
|
!['KeyJ', 'KeyK', 'KeyI', 'KeyO', 'ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft',].includes(keyCode)
|
&& !droneControl
|
) {
|
return
|
}
|
if (downKeyCode !== keyCode){
|
downKeyCode = keyCode
|
downTime = Date.now()
|
}
|
const {droneSn,speed} = paramsRef.value
|
genPortOne = droneSn === '1581F5BMD22CK0014H2U' || droneSn === 'BA0BA1C3D38157A49E1B16574FA474F7';
|
const exactMapping = [0,3,5,6,7,8,9,10,11,12,12,13,14,14,15,15]
|
const SPEED = genPortOne ? speed : (exactMapping[speed] * 44)
|
const HEIGHT = genPortOne ? 5 : 500; // check
|
// 机头角速度 一代-90, 90,二三代 -600,600
|
const W_SPEED = genPortOne ? 90 : 600
|
|
let arrList = []
|
if (genPortOne) {
|
arrList = [
|
{ Key: 'KeyQ', category: 'w', value: -W_SPEED },{ Key: 'KeyW',category: 'x', value: SPEED },
|
{ Key: 'KeyE', category: 'w', value: W_SPEED},{ Key: 'KeyA', category: 'y', value: -SPEED},
|
{ Key: 'KeyS', category: 'x', value: -SPEED},{ Key: 'KeyD', category: 'y', value: SPEED}
|
]
|
} else {
|
arrList = [
|
{ Key: 'KeyQ', category: 'yaw', value: 1024-W_SPEED },{ Key: 'KeyW',category: 'pitch', value: 1024+SPEED },
|
{ Key: 'KeyE', category: 'yaw', value: 1024+W_SPEED},{ Key: 'KeyA', category: 'roll', value: 1024-SPEED},
|
{ Key: 'KeyS', category: 'pitch', value: 1024-SPEED},{ Key: 'KeyD', category: 'roll', value: 1024+SPEED}
|
]
|
}
|
let resultObj = []
|
let resultArr = []
|
// 遍历被选中得数组
|
if (keyCode === 'assemblyKeys') {
|
keysPressed.map(key => {
|
if (key.value) {
|
let result = arrList.filter(item =>item.Key===key.key)
|
resultObj.push(result[0])
|
}
|
})
|
// 相同属性值进行计算
|
resultArr = resultObj.reduce((acc, item) => {
|
// 如果累加器中已经有这个 category,则累加 value
|
if (acc[item.category]) {
|
// acc[item.category] += item.value;
|
acc[item.category] = genPortOne ? 0 : 1024;
|
} else {
|
// 否则,初始化这个 category 的 value
|
acc[item.category] = item.value;
|
}
|
return acc;
|
}, {});
|
}
|
|
seq = 0
|
switch (keyCode) {
|
case 'assemblyKeys': // 针对Q W E A S D 组合键
|
if (activeCodeKey === keyCode) return
|
handlePublish(resultArr)
|
activeCodeKey = keyCode
|
break
|
case 'KeyQ':
|
if (activeCodeKey === keyCode) return
|
console.log(88888888888888)
|
let objQ = { yaw: 1024-W_SPEED }
|
if (genPortOne) {objQ = {w: -W_SPEED}}
|
handlePublish(objQ)
|
activeCodeKey = keyCode
|
break
|
case 'KeyW':
|
if (activeCodeKey === keyCode) return
|
let objW = { pitch: 1024+SPEED }
|
if (genPortOne) {objW = {x: SPEED}}
|
handlePublish(objW)
|
activeCodeKey = keyCode
|
break
|
case 'KeyE':
|
if (activeCodeKey === keyCode) return
|
let objE = { yaw: 1024+W_SPEED }
|
if (genPortOne) {objE = {w: W_SPEED}}
|
handlePublish(objE)
|
activeCodeKey = keyCode
|
break
|
case 'KeyA':
|
if (activeCodeKey === keyCode) return
|
let objA = { roll: 1024-SPEED }
|
if (genPortOne) {objA = {y: -SPEED}}
|
handlePublish(objA)
|
activeCodeKey = keyCode
|
break
|
case 'KeyS':
|
if (activeCodeKey === keyCode) return
|
let objS = { pitch: 1024-SPEED }
|
if (genPortOne) {objS = {x: -SPEED}}
|
handlePublish(objS)
|
activeCodeKey = keyCode
|
break
|
case 'KeyD':
|
if (activeCodeKey === keyCode) return
|
let objD = { roll: 1024+SPEED }
|
if (genPortOne) {objD = {y: SPEED}}
|
handlePublish(objD)
|
activeCodeKey = keyCode
|
break
|
case 'KeyZ':
|
if (activeCodeKey === keyCode) return
|
let objZ = { throttle: 1024-HEIGHT }
|
if (genPortOne) {objZ = {h: -HEIGHT}}
|
handlePublish(objZ)
|
activeCodeKey = keyCode
|
break
|
case 'KeyC':
|
if (activeCodeKey === keyCode) return
|
let objC = { throttle: 1024+HEIGHT }
|
if (genPortOne) {objC = {h: HEIGHT}}
|
handlePublish(objC)
|
activeCodeKey = keyCode
|
break
|
case 'NumpadAdd':
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('controlPanel-editSpeed',1)
|
activeCodeKey = keyCode
|
break
|
case 'NumpadSubtract':
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('controlPanel-editSpeed',-1)
|
activeCodeKey = keyCode
|
break
|
case 'ArrowUp':
|
if (activeCodeKey === keyCode) return
|
ptzControlInterval('up')
|
activeCodeKey = keyCode
|
break
|
case 'ArrowDown':
|
if (activeCodeKey === keyCode) return
|
ptzControlInterval('down')
|
activeCodeKey = keyCode
|
break
|
case 'ArrowLeft':
|
if (activeCodeKey === keyCode) return
|
ptzControlInterval('left')
|
activeCodeKey = keyCode
|
break
|
case 'ArrowRight':
|
if (activeCodeKey === keyCode) return
|
ptzControlInterval('right')
|
activeCodeKey = keyCode
|
break
|
case 'KeyJ': //拍照
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('TaskDetailsLeft-takePictures')
|
activeCodeKey = keyCode
|
break
|
case 'KeyK'://录像
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('TaskDetailsLeft-recordFun')
|
activeCodeKey = keyCode
|
break
|
case 'KeyI': //放大变焦
|
if (activeCodeKey === keyCode) return
|
zoomFactorChange(1)
|
activeCodeKey = keyCode
|
break
|
case 'KeyO': //缩小变焦
|
if (activeCodeKey === keyCode) return
|
zoomFactorChange(0)
|
activeCodeKey = keyCode
|
break
|
case 'KeyX': //悬停
|
break
|
case 'KeyB': // 文字转广播
|
if (!isManualControl.value) {
|
return ElMessage.warning('请先接管!')
|
}
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('TaskDetailsLeft-txtShoutList', 'keyB')
|
activeCodeKey = keyCode
|
break
|
case 'KeyN': // 喊话
|
if (!isManualControl.value) {
|
return ElMessage.warning('请先接管!')
|
}
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('TaskDetailsLeft-shoutList', 'videoNKey')
|
activeCodeKey = keyCode
|
break
|
case 'KeyM': //广播
|
if (!isManualControl.value) {
|
return ElMessage.warning('请先接管!')
|
}
|
if (activeCodeKey === keyCode) return
|
EventBus.emit('TaskDetailsLeft-broadcastList', 'keyM')
|
activeCodeKey = keyCode
|
break
|
default:
|
break
|
}
|
}
|
|
function ptzControl(key) {
|
let pitchSpeed = ptzKeyHandle()
|
const {dockSn} = paramsRef.value
|
if (key === 'down' || key === 'left'){
|
pitchSpeed = -pitchSpeed
|
}
|
ptzControlApi(key, { sn: dockSn,pitchSpeed })
|
}
|
// 云台控制上下左右
|
function ptzControlInterval(key){
|
handleClearInterval()
|
ptzControl(key)
|
myInterval = setInterval(()=>ptzControl(key), 200)
|
}
|
|
// 按键变焦
|
const zoomFactorControl = _.throttle((amplify)=>{
|
let zoom = getZoomFactor()
|
zoom = amplify ? zoom : (zoom * -1)
|
EventBus.emit('TaskDetailsLeft-quickZoomIn', zoom)
|
},1000)
|
|
function zoomFactorChange(amplify) {
|
handleClearInterval()
|
zoomFactorControl(amplify)
|
myInterval = setInterval(()=>zoomFactorControl(amplify), 1000)
|
}
|
|
|
function handleClearInterval() {
|
clearInterval(myInterval)
|
myInterval = undefined
|
}
|
|
// 重置所有控制状态
|
function resetControlState() {
|
downTime = null
|
downKeyCode = null
|
keysPressed.map(item => (item.value = false))
|
activeCodeKey = null
|
seq = 0
|
handleClearInterval()
|
}
|
|
// 按键弹起
|
function onKeyup(e) {
|
if (store?.state?.task?.keysDisabled) return
|
keysPressed.forEach(item => {
|
if (e.code === item.key) item.value = false
|
})
|
const keyList = keysPressed.filter(item => item.value === true);
|
if (keyList.length === 1) {
|
handleKeyup(keyList[0].key);
|
} else {
|
resetControlState();
|
}
|
activeBtnList.value = keyList.map(i => i.key)
|
}
|
|
let timedReset = _.debounce(resetControlState,2000)
|
// 按键按下
|
function onKeydown(e) {
|
if (store?.state?.task?.keysDisabled) return
|
e.preventDefault()
|
keysPressed.forEach(item => {
|
if(e.code === item.key) item.value = true
|
})
|
let result = keysPressed.filter(item=>item.value===true)
|
if (result && result.length >= 2) {
|
handleKeyup('assemblyKeys')
|
} else {
|
handleKeyup(e.code)
|
}
|
// 保底措施,避免长时间不操作导致控制状态不重置
|
timedReset()
|
activeBtnList.value = result.map(i => i.key)
|
}
|
|
// 紧急停止
|
function handleEmergencyStop() {
|
resetControlState()
|
if (!deviceTopicInfo.pubTopic) {
|
ElMessage.error('请确保已经建立DRC链路')
|
return
|
}
|
const body = {
|
method: DRC_METHOD.DRONE_EMERGENCY_STOP,
|
data: {},
|
}
|
window.console.log('handleEmergencyStop>>>>', deviceTopicInfo.pubTopic, body)
|
mqttHooks?.publishMqtt(deviceTopicInfo.pubTopic, body, { qos: 1 })
|
}
|
|
function openKeyMonitor() {
|
removeKeyMonitor()
|
console.log('开启键盘监听事件')
|
window.addEventListener('keydown', onKeydown)
|
window.addEventListener('keyup', onKeyup)
|
}
|
function removeKeyMonitor() {
|
resetControlState()
|
console.log('关闭键盘监听事件')
|
window.removeEventListener('keydown', onKeydown)
|
window.removeEventListener('keyup', onKeyup)
|
}
|
|
return {
|
activeCodeKey,
|
handleKeyup,
|
handleEmergencyStop,
|
resetControlState,
|
openKeyMonitor,
|
removeKeyMonitor,
|
}
|
}
|