diff --git a/src/apis/robot/api.ts b/src/apis/robot/api.ts index 7e8ad80..d587a54 100644 --- a/src/apis/robot/api.ts +++ b/src/apis/robot/api.ts @@ -1,6 +1,6 @@ import http from '@core/http'; -import type { RobotDetail, RobotGroup, RobotInfo } from './type'; +import type { AmrRedisState, RobotDetail, RobotGroup, RobotInfo } from './type'; const enum API { 获取所有机器人 = '/robot/getAll', @@ -9,6 +9,7 @@ const enum API { 批量抢占控制权 = '/robot/seizeByIds', 同步组文件 = '/robot/syncByGroupId', + 获取AMR状态 = '/amr/redis', } export async function getAllRobots(): Promise> { @@ -62,3 +63,14 @@ export async function syncGroupRobotsById(id: RobotGroup['id'], sid: RobotGroup[ return false; } } + +export async function getAmrRedisState(id: string): Promise { + type D = AmrRedisState; + try { + const data = await http.get(`${API.获取AMR状态}/${id}`); + return data ?? null; + } catch (error) { + console.debug(error); + return null; + } +} diff --git a/src/apis/robot/type.ts b/src/apis/robot/type.ts index e27ca2e..e9d8e26 100644 --- a/src/apis/robot/type.ts +++ b/src/apis/robot/type.ts @@ -46,3 +46,91 @@ export interface RobotRealtimeInfo extends RobotInfo { isWaring?: boolean; // 是否告警 isFault?: boolean; // 是否故障 } + +// AMR Redis状态接口 +export interface AmrRedisState { + headerid: number; + timestamp: string; + version: string; + manufacturer: string; + serialnumber: string; + orderid: string; + orderupdateid: number; + lastnodeid: string; + lastnodesequenceid: number; + driving: boolean; + waitingforinteractionzonerelease: boolean; + paused: boolean; + newbaserequest: boolean; + distancesincelastnode: number; + operatingmode: string; + nodestates: any[]; + edgestates: any[]; + agvposition: { + x: number; + y: number; + theta: number; + mapid: string; + mapdescription: string; + positioninitialized: boolean; + deviationrange: number; + localizationscore: number; + }; + velocity: { + vx: number; + vy: number; + omega: number; + }; + loads: Array<{ + loadid: string; + loadtype: string; + loadposition: string; + boundingboxreference: { + x: number; + y: number; + z: number; + theta: number; + }; + loaddimensions: { + length: number; + width: number; + height: number; + }; + }>; + actionstates: Array<{ + actionid: string; + actiontype: string; + actiondescription: string; + actionstatus: string; + resultdescription: string; + }>; + batterystate: { + batterycharge: number; + batteryvoltage: number; + batteryhealth: number; + charging: boolean; + reach: number; + }; + errors: Array<{ + errortype: string; + errorreferences: Array<{ + referencekey: string; + referencevalue: string; + }>; + errordescription: string; + errorlevel: string; + }>; + information: Array<{ + infotype: string; + inforeferences: Array<{ + referencekey: string; + referencevalue: string; + }>; + infodescription: string; + infolevel: string; + }>; + safetystate: { + estop: string; + fieldviolation: boolean; + }; +} diff --git a/src/components/card/robot-detail-card.vue b/src/components/card/robot-detail-card.vue index 2faead0..1ef9988 100644 --- a/src/components/card/robot-detail-card.vue +++ b/src/components/card/robot-detail-card.vue @@ -1,8 +1,8 @@ + + + + + +
+ +
+ + {{ $t('原始数据') }} + +
+ + + + + + {{ amrDetailData.serialnumber || '-' }} + {{ amrDetailData.manufacturer || '-' }} + {{ amrDetailData.version || '-' }} + {{ amrDetailData.orderid || '-' }} + {{ amrDetailData.lastnodeid || '-' }} + {{ + amrDetailData.operatingmode || '-' + }} + {{ + amrDetailData.driving ? $t('是') : $t('否') + }} + {{ + amrDetailData.paused ? $t('是') : $t('否') + }} + {{ + amrDetailData.timestamp || '-' + }} + {{ (amrDetailData.distancesincelastnode || 0).toFixed(2) }}m + {{ + amrDetailData.waitingforinteractionzonerelease ? $t('是') : $t('否') + }} + + + + + + {{ + amrDetailData.agvposition?.x?.toFixed(4) || '-' + }} + {{ + amrDetailData.agvposition?.y?.toFixed(4) || '-' + }} + {{ + amrDetailData.agvposition?.theta?.toFixed(4) || '-' + }} + {{ + amrDetailData.agvposition?.mapid || '-' + }} + {{ + amrDetailData.agvposition?.localizationscore?.toFixed(4) || '-' + }} + {{ + amrDetailData.agvposition?.deviationrange?.toFixed(4) || '-' + }} + + + + + + {{ amrDetailData.batterystate?.batterycharge?.toFixed(1) || '-' }}% + {{ amrDetailData.batterystate?.batteryvoltage?.toFixed(3) || '-' }}V + {{ amrDetailData.batterystate?.batteryhealth || '-' }}% + {{ + amrDetailData.batterystate?.charging ? $t('是') : $t('否') + }} + {{ amrDetailData.batterystate?.reach?.toFixed(1) || '-' }}km + + + + + + {{ amrDetailData.velocity?.vx?.toFixed(3) || '-' }}m/s + {{ amrDetailData.velocity?.vy?.toFixed(3) || '-' }}m/s + {{ amrDetailData.velocity?.omega?.toFixed(3) || '-' }}rad/s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ amrDetailData.safetystate?.estop || '-' }} + + + + + {{ amrDetailData.safetystate?.fieldviolation ? $t('是') : $t('否') }} + + + + + + + + + +
+
+ +
+
@@ -112,4 +345,60 @@ const stateDot = computed(() => `state-${robot.value?.state}`); } } } + +.amr-detail-content { + .ant-tabs-content { + max-height: 600px; + overflow-y: auto; + } + + .ant-descriptions { + margin-bottom: 16px; + } + + .ant-table { + margin-bottom: 16px; + } + + .font-mono { + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 12px; + line-height: 1.5; + } + + .mt-16 { + margin-top: 16px; + } + + .icon { + margin-right: 4px; + } +} + +.error-content { + .mb-16 { + margin-bottom: 16px; + } +} + +// 弹窗标题样式 +:deep(.ant-modal-header) { + .flex { + display: flex; + align-items: center; + justify-content: space-between; + } + + .text-xs { + font-size: 12px; + } + + .text-gray-500 { + color: #6b7280; + } + + .mt-1 { + margin-top: 4px; + } +}