Browse Source

库存监视 InvUpdate

master
修宁 5 months ago
parent
commit
d0f134c9ef
  1. 2
      src/core/base/BaseRenderer.ts
  2. 53
      src/core/manager/EnvManager.ts
  3. 20
      src/core/manager/RuntimeManager.ts
  4. 41
      src/core/script/LCCScript.ts
  5. 5
      src/core/script/ModelManager.ts
  6. 64
      src/types/LCC.d.ts

2
src/core/base/BaseRenderer.ts

@ -147,7 +147,7 @@ export default abstract class BaseRenderer {
if (item.dt.storeAt?.item) { if (item.dt.storeAt?.item) {
// 如果是库存物品, 则需要将位置和角度设置为库存位置 // 如果是库存物品, 则需要将位置和角度设置为库存位置
const rack = this.tempViewport.stateManager.findItemById(item.dt.storeAt?.item) const rack = Model.find(item.dt.storeAt?.item)
if (!rack) { if (!rack) {
console.error(`Cannot find rack for item ${item.id} at ${item.dt.storeAt?.item}`) console.error(`Cannot find rack for item ${item.id} at ${item.dt.storeAt?.item}`)
} }

53
src/core/manager/EnvManager.ts

@ -9,6 +9,7 @@ import { AmrMsg } from '@/core/manager/amr/AmrMessageDefine'
export default class EnvManager { export default class EnvManager {
private amrMessageManager: AmrMessageManager = new AmrMessageManager() private amrMessageManager: AmrMessageManager = new AmrMessageManager()
public client: mqtt.MqttClient = null public client: mqtt.MqttClient = null
readonly stopSubscribe: StopSubscribe[] = []
onMqttConnect = (packet: IConnackPacket) => { onMqttConnect = (packet: IConnackPacket) => {
console.log('Connected') console.log('Connected')
@ -57,7 +58,10 @@ export default class EnvManager {
const env = worldModel.state.runState.currentEnv const env = worldModel.state.runState.currentEnv
try { try {
worldModel.backendMessageReceiver.setProjectEnv(worldModel.state.project_uuid, worldModel.state.runState.currentEnvId) worldModel.backendMessageReceiver.setProjectEnv(worldModel.state.project_uuid, worldModel.state.runState.currentEnvId)
await LCC.loadInv() await this.loadInvToModel()
this.stopSubscribe.push(
worldModel.backendMessageReceiver.subscribe('InvUpdate', this.onInvUpdateMessage.bind(this))
)
this.client = mqtt.connect(env.envConfig.mqtt.websocket, { this.client = mqtt.connect(env.envConfig.mqtt.websocket, {
path: '/mqtt', path: '/mqtt',
@ -83,6 +87,47 @@ export default class EnvManager {
} }
} }
async onInvUpdateMessage(type: BackendTopicType, topic: string, body: InvUpdateVo) {
if (!window['Model']) {
// 如果没有3D模型加载,则不处理库存更新
return
}
const lpnItem = Model.find(body.lpn)
if (lpnItem) {
Model.deleteItem(lpnItem.id)
}
if (body.after != null) {
// 将托盘挪到目标位置
const after = body.after
Model.createInv('pallet', body.lpn, after.rack, after.bay, after.level, after.cell)
}
}
// 加载库存到3D视图上
async loadInvToModel() {
if (!window['Model']) {
return
}
const invRes = await LCC.loadInv()
if (!invRes.success) {
return
}
for (const row of invRes.data) {
const bay = row.bay
const cell = row.cell // : 0
const level = row.level // : 0
const loc_code = row.loc_code // : "rack1_0_0_0"
const lpn = row.lpn // : "LPN1"
const rack = row.rack // : "rack1"
const container_type = row.container_type // : "pallet"
Model.createInv(container_type, lpn, rack, bay, level, cell)
}
}
// 加载执行器到3D视图上 // 加载执行器到3D视图上
async loadExecutorToModel() { async loadExecutorToModel() {
if (!window['Model']) { if (!window['Model']) {
@ -128,6 +173,12 @@ export default class EnvManager {
system.showLoading() system.showLoading()
try { try {
worldModel.state.runState.isRunning = false worldModel.state.runState.isRunning = false
for (const stopFn of this.stopSubscribe) {
stopFn()
}
this.stopSubscribe.length = 0
if (this.client) { if (this.client) {
this.client.removeAllListeners() this.client.removeAllListeners()
this.client.end() this.client.end()

20
src/core/manager/RuntimeManager.ts

@ -78,4 +78,24 @@ export default class RuntimeManager {
this.tmpExecutors.add(item.id) this.tmpExecutors.add(item.id)
this.viewport.entityManager.createOrUpdateEntityOnlyRuntime(item) this.viewport.entityManager.createOrUpdateEntityOnlyRuntime(item)
} }
removeEntity(itemId: string) {
this.tmpExecutors.delete(itemId)
// 从各个货架中移除
for (const [rackId, items] of this.storeRackMap.entries()) {
if (items.has(itemId)) {
items.delete(itemId)
if (items.size === 0) {
this.storeRackMap.delete(rackId)
}
}
}
this.viewport.entityManager.deleteEntityOnlyRuntime(itemId)
}
has(itemId: string) {
return this.tmpExecutors.has(itemId)
}
} }

41
src/core/script/LCCScript.ts

@ -57,25 +57,38 @@ export default class LCCScript implements LCC {
} }
// 从后台读取所有库存 // 从后台读取所有库存
async loadInv(): Promise<ServerResponse<InvVo>> { async loadInv(): Promise<ServerResponse<InvVo[]>> {
const res = await Request.request.post('/api/workbench/LccController@loadInv', { return Request.request.post('/api/workbench/InvController@loadInv', {
projectUuid: worldModel.state.project_uuid, projectUUID: worldModel.state.project_uuid,
catalogCode: worldModel.state.catalogCode, catalogCode: worldModel.state.catalogCode,
envId: worldModel.state.runState.currentEnvId envId: worldModel.state.runState.currentEnvId
}) })
for (const row of res.data) {
const bay = row.bay
const cell = row.cell // : 0
const level = row.level // : 0
const loc_code = row.loc_code // : "rack1_0_0_0"
const lpn = row.lpn // : "LPN1"
const rack = row.rack // : "rack1"
const container_type = row.container_type // : "pallet"
if (window['Model']) {
Model.createInv(container_type, lpn, rack, bay, level, cell)
} }
createInv(lpn: string, targetStore: string): Promise<ServerResponse<void>> {
return Request.request.post('/api/workbench/InvController@createInv', {
projectUUID: worldModel.state.project_uuid,
envId: worldModel.state.runState.currentEnvId,
lpn: lpn,
targetStore: targetStore
})
}
moveInv(lpn: string, targetStore: string): Promise<ServerResponse<void>> {
return Request.request.post('/api/workbench/InvController@moveInv', {
projectUUID: worldModel.state.project_uuid,
envId: worldModel.state.runState.currentEnvId,
lpn: lpn,
targetStore: targetStore
})
} }
return res.data
deleteInv(lpn: string): Promise<ServerResponse<void>> {
return Request.request.post('/api/workbench/InvController@deleteInv', {
projectUUID: worldModel.state.project_uuid,
envId: worldModel.state.runState.currentEnvId,
lpn: lpn
})
} }
saveAndSyncScripts(scriptList: { name: string; content: string }[]): Promise<ServerResponse<{ name: string; content: string }[]>> { saveAndSyncScripts(scriptList: { name: string; content: string }[]): Promise<ServerResponse<{ name: string; content: string }[]>> {

5
src/core/script/ModelManager.ts

@ -86,6 +86,11 @@ export default class ModelManager implements IControls, Model {
} }
deleteItem(itemId) { deleteItem(itemId) {
if(this.viewport.runtimeManager.has(itemId)){
// 临时执行器
this.viewport.runtimeManager.removeEntity(itemId)
return
}
this.viewport.stateManager.update(({ deleteEntity }) => { this.viewport.stateManager.update(({ deleteEntity }) => {
deleteEntity(itemId) deleteEntity(itemId)
}) })

64
src/types/LCC.d.ts

@ -16,11 +16,32 @@ declare interface LCC {
/** /**
* , Model * , Model
*/ */
loadInv(): Promise<ServerResponse<InvVo>> loadInv(): Promise<ServerResponse<InvVo[]>>
/**
*
* @param lpn
* @param targetStore rack3/0/0/0
*/
createInv(lpn: string, targetStore: string): Promise<ServerResponse<void>>
/**
*
* @param lpn
* @param targetStore rack3/0/0/0
*/
moveInv(lpn: string, targetStore: string): Promise<ServerResponse<void>>
/**
*
* @param lpn
*/
deleteInv(lpn: string): Promise<ServerResponse<void>>
/** /**
* Model * Model
*/ */
// loadExecutor(): Promise<ExecutorVo> // loadExecutor(): Promise<ExecutorVo>
/** /**
@ -77,6 +98,8 @@ type DeviceStatusFn = (type: BackendTopicType, topic: string, body: AgvStatusVo)
type ServerStateFn = (type: BackendTopicType, topic: string, body: ServerStatusVo) => void type ServerStateFn = (type: BackendTopicType, topic: string, body: ServerStatusVo) => void
type InvUpdateFn = (type: BackendTopicType, topic: string, body: InvUpdateVo) => void
type StopSubscribe = () => void type StopSubscribe = () => void
interface ServerAuthorizationConfigVo { interface ServerAuthorizationConfigVo {
@ -169,6 +192,45 @@ interface AgvStatusVo {
virtualExecutorPayload: string; // 车的虚拟执行器负载 virtualExecutorPayload: string; // 车的虚拟执行器负载
} }
interface BasLocationVo {
/**
*
*/
locCode: string
/**
*
*/
locType: string
/**
*
*/
rack: string
/**
*
*/
bay: number
/**
*
*/
level: number
/**
*
*/
cell: number
}
interface InvUpdateVo {
lpn: string
before: BasLocationVo | null
after: BasLocationVo | null
qty: number
}
/** /**
* *
*/ */

Loading…
Cancel
Save