Browse Source

连接到已带状态的服务器

master
修宁 5 months ago
parent
commit
b40017dac4
  1. 43
      src/core/manager/EnvManager.ts
  2. 94
      src/core/script/LCCScript.ts
  3. 3
      src/core/script/ModelManager.ts
  4. 24
      src/editor/widgets/monitor/MonitorView.vue
  5. 10
      src/types/LCC.d.ts

43
src/core/manager/EnvManager.ts

@ -70,7 +70,7 @@ export default class EnvManager {
keepalive: 60 keepalive: 60
}) })
await LCC.loadExecutor() await this.loadExecutorToModel()
this.client.on('connect', this.onMqttConnect) this.client.on('connect', this.onMqttConnect)
this.client.on('message', this.onMqttMessage) this.client.on('message', this.onMqttMessage)
@ -83,6 +83,47 @@ export default class EnvManager {
} }
} }
// 加载执行器到3D视图上
async loadExecutorToModel() {
if (!window['Model']) {
return
}
const deviceRes = await LCC.queryDeviceInfoList()
if (!deviceRes.success) {
return
}
const deviceList: AgvStatusVo[] = deviceRes.data || []
for (const agvState of deviceList) {
const agvItem = Model.find(agvState.id)
if (!agvItem) {
// 还没加载到地图
const item = JSON.parse(agvState.virtualExecutorPayload)
const pos = Model.getPositionByLogicXY(agvState.logicX, agvState.logicY)
if (pos) {
item.tf[0] = [pos.x, pos.y, agvState.z]
}
switch (_.toLower(agvState.direction)) {
// right=0/left=180/up=90/down=-90
case 'right':
item.tf[1][1] = 0 // 右侧
break
case 'left':
item.tf[1][1] = 180 // 左侧
break
case 'down':
item.tf[1][1] = -90 // 下方
break
case 'up':
item.tf[1][1] = 90 // 上方
break
}
Model.createExecutor(item)
}
}
}
async disconnectEnv() { async disconnectEnv() {
system.showLoading() system.showLoading()
try { try {

94
src/core/script/LCCScript.ts

@ -90,59 +90,59 @@ export default class LCCScript implements LCC {
}) })
} }
queryDeviceInfoList(): Promise<ServerResponse<DeviceVo[]>> { queryDeviceInfoList(): Promise<ServerResponse<AgvStatusVo[]>> {
return Request.request.post('/api/workbench/LccController@queryDeviceInfoList', { return Request.request.post('/api/workbench/LccController@queryDeviceInfoList', {
projectUUID: worldModel.state.project_uuid, projectUUID: worldModel.state.project_uuid,
envId: worldModel.state.runState.currentEnvId envId: worldModel.state.runState.currentEnvId
}) })
} }
// 从后台读取所有车 // // 从后台读取所有车
async loadExecutor(): Promise<ExecutorVo> { // async loadExecutor(): Promise<ExecutorVo> {
const res = await Request.request.post('/api/workbench/LccController@loadExecutor', { // const res = await Request.request.post('/api/workbench/LccController@loadExecutor', {
projectUuid: worldModel.state.project_uuid, // projectUuid: worldModel.state.project_uuid,
envId: worldModel.state.runState.currentEnvId // envId: worldModel.state.runState.currentEnvId
}) // })
//
for (const row of res.data) { // for (const row of res.data) {
const executor_id = row.executor_id // const executor_id = row.executor_id
const payload = JSON.parse(row.virtual_executor_payload) // const payload = JSON.parse(row.virtual_executor_payload)
// 车所在的标记位置,及方向 11_4:RIGHT // // 车所在的标记位置,及方向 11_4:RIGHT
const [wayPointId, direction] = _.split(row.virtual_location_at, ':') // const [wayPointId, direction] = _.split(row.virtual_location_at, ':')
//
if (window['Model']) { // if (window['Model']) {
const point = Model.find(wayPointId) // const point = Model.find(wayPointId)
if (!point) { // if (!point) {
console.error(`Waypoint with ID ${wayPointId} not found for executor ${executor_id}.`) // console.error(`Waypoint with ID ${wayPointId} not found for executor ${executor_id}.`)
continue // continue
} // }
//
const item = _.cloneDeep(payload) // const item = _.cloneDeep(payload)
item.id = executor_id // item.id = executor_id
item.tf[0] = _.cloneDeep(point.tf[0]) // item.tf[0] = _.cloneDeep(point.tf[0])
switch (_.toLower(direction)) { // switch (_.toLower(direction)) {
// right=0/left=180/up=90/down=-90 // // right=0/left=180/up=90/down=-90
case 'right': // case 'right':
item.tf[1][1] = 0 // 右侧 // item.tf[1][1] = 0 // 右侧
break // break
case 'left': // case 'left':
item.tf[1][1] = 180 // 左侧 // item.tf[1][1] = 180 // 左侧
break // break
case 'down': // case 'down':
item.tf[1][1] = -90 // 下方 // item.tf[1][1] = -90 // 下方
break // break
case 'up': // case 'up':
item.tf[1][1] = 90 // 上方 // item.tf[1][1] = 90 // 上方
break // break
} // }
if (row.virtual_floor_code === worldModel.state.catalogCode) { // if (row.virtual_floor_code === worldModel.state.catalogCode) {
Model.createExecutor(item) // Model.createExecutor(item)
} // }
} // }
} // }
//
return res.data // return res.data
} // }
/** /**
* *

3
src/core/script/ModelManager.ts

@ -142,6 +142,9 @@ this.viewport.stateManager.update(({ getEntity, putEntity, addEntity }) => {
getPositionByLogicXY(logicX: number, logicY: number): THREE.Vector3 { getPositionByLogicXY(logicX: number, logicY: number): THREE.Vector3 {
const item = this.viewport.entityManager.findItemByLogicXY(logicX, logicY) const item = this.viewport.entityManager.findItemByLogicXY(logicX, logicY)
if (!item) {
return null
}
const matrix = getMatrixFromTf(item.tf) const matrix = getMatrixFromTf(item.tf)
const position = new THREE.Vector3() const position = new THREE.Vector3()
matrix.decompose(position, new THREE.Quaternion(), new THREE.Vector3()) matrix.decompose(position, new THREE.Quaternion(), new THREE.Vector3())

24
src/editor/widgets/monitor/MonitorView.vue

@ -1,11 +1,15 @@
<template> <template>
<div class="title"> <div class="title">
设备监控 设备监控
<el-button size="small" :icon="renderIcon('Refresh')" @click="refreshData"
style="margin-left: 5px;"
/>
<el-input v-model="searchKeyword" size="small" style="width: 240px" placeholder="Search"> <el-input v-model="searchKeyword" size="small" style="width: 240px" placeholder="Search">
<template #prefix> <template #prefix>
<component :is="renderIcon('element Search')"></component> <component :is="renderIcon('element Search')"></component>
</template> </template>
</el-input> </el-input>
<span class="close" @click="closeMe"> <span class="close" @click="closeMe">
<component :is="renderIcon('element Close')" /> <component :is="renderIcon('element Close')" />
</span> </span>
@ -76,7 +80,7 @@ export default {
stopSubscribe: [], stopSubscribe: [],
/** /**
* 设备列表数据 * 设备列表数据
* @type {Array< Partial< DeviceVo>>} * @type {Array<Partial<AgvStatusVo>>}
*/ */
deviceList: [] deviceList: []
} }
@ -100,7 +104,7 @@ export default {
* 获取任务进度百分比 * 获取任务进度百分比
*/ */
getTaskProcessPercent(deviceInfo) { getTaskProcessPercent(deviceInfo) {
if (deviceInfo == null || deviceInfo.taskTotalCount === 0) { if (deviceInfo == null || !deviceInfo.taskTotalCount || !deviceInfo.taskCompleted) {
return 0 return 0
} }
return Math.round((deviceInfo.taskCompleted / deviceInfo.taskTotalCount) * 100) return Math.round((deviceInfo.taskCompleted / deviceInfo.taskTotalCount) * 100)
@ -133,7 +137,6 @@ export default {
* @type {DeviceStatusFn} * @type {DeviceStatusFn}
*/ */
onDeviceStatusMessage(type, topic, body) { onDeviceStatusMessage(type, topic, body) {
console.log(this, topic, body)
const deviceInfo = _.find(this.deviceList, device => device.id === body.id) const deviceInfo = _.find(this.deviceList, device => device.id === body.id)
if (!deviceInfo) { if (!deviceInfo) {
return return
@ -141,12 +144,7 @@ export default {
_.assign(deviceInfo, body) _.assign(deviceInfo, body)
}, },
async subscribe() { async subscribe() {
this.deviceList = [] await this.refreshData()
const res = await LCC.queryDeviceInfoList()
if (!res.success) {
return
}
this.deviceList = res.data
// //
this.stopSubscribe.push( this.stopSubscribe.push(
@ -156,6 +154,14 @@ export default {
worldModel.backendMessageReceiver.subscribe('DeviceStatus', this.onDeviceStatusMessage.bind(this)) worldModel.backendMessageReceiver.subscribe('DeviceStatus', this.onDeviceStatusMessage.bind(this))
) )
}, },
async refreshData(){
this.deviceList = []
const res = await LCC.queryDeviceInfoList()
if (!res.success) {
return
}
this.deviceList = res.data
},
undescribe() { undescribe() {
// //
for (const stopFn of this.stopSubscribe) { for (const stopFn of this.stopSubscribe) {

10
src/types/LCC.d.ts

@ -21,7 +21,7 @@ declare interface LCC {
/** /**
* Model * Model
*/ */
loadExecutor(): Promise<ExecutorVo> // loadExecutor(): Promise<ExecutorVo>
/** /**
* *
@ -32,7 +32,7 @@ declare interface LCC {
/** /**
* *
*/ */
queryDeviceInfoList(): Promise<ServerResponse<DeviceVo[]>> queryDeviceInfoList(): Promise<ServerResponse<AgvStatusVo[]>>
/** /**
* *
@ -73,7 +73,7 @@ type BackendTopicType = 'ServerState' | 'ClientState' | 'TaskUpdate' | 'InvUpdat
type DeviceAliveFn = (type: BackendTopicType, topic: string, body: DeviceAliveVo) => void type DeviceAliveFn = (type: BackendTopicType, topic: string, body: DeviceAliveVo) => void
type DeviceStatusFn = (type: BackendTopicType, topic: string, body: DeviceVo) => void type DeviceStatusFn = (type: BackendTopicType, topic: string, body: AgvStatusVo) => void
type ServerStateFn = (type: BackendTopicType, topic: string, body: ServerStatusVo) => void type ServerStateFn = (type: BackendTopicType, topic: string, body: ServerStatusVo) => void
@ -112,7 +112,7 @@ interface DeviceAliveVo {
online: boolean online: boolean
} }
interface DeviceVo { interface AgvStatusVo {
// 设备 ID // 设备 ID
id: string id: string
// 设备类型 // 设备类型
@ -165,6 +165,8 @@ interface DeviceVo {
bizTaskTo: string bizTaskTo: string
// 搬运托盘号 // 搬运托盘号
bizLpn: string bizLpn: string
virtualLocationAt: string; // 车所在的标记位置,及方向 11_4:RIGHT
virtualExecutorPayload: string; // 车的虚拟执行器负载
} }
/** /**

Loading…
Cancel
Save