2024-09-05 17:24:50 +08:00

360 lines
12 KiB
Plaintext

import common from '@ohos.app.ability.common';
import RealTime from '../components/RealTime';
import { MediaPlayer } from '../utils/MediaPlayer';
import { CommandType, MessageCallBackParams, SimulatorUdpClient } from '../utils/simulator/UdpClient';
import { BackMachineUdpClient } from '../utils/udp/UdpClient';
import { ConfigItemProps, ConfigProps, Status } from '../model/index';
import { getConfigFile } from '../utils/native/NativeUtils';
import promptAction from '@ohos.promptAction';
import { OutWireControl } from '../utils/wireControl/OutWireControl';
import {
nativeLogCallback,
nativeSDKInit,
onTrack,
registerControlCallback,
registerSoundCallback,
selectLineAndLib,
setConfigFile,
setImageSize
} from '../utils/native/NativeSDK';
import { LogHelper } from '../utils/LogHelper';
import util from '@ohos.util';
import { CarInfo, GpsInfo, parseCar, parseGps } from '../utils/udp/Gps';
// 直角转弯 (0, 0) (0, 1) ...
// 坡道起步 (1, 0) (1, 1) ...
// 倒车入库 (2, 0) (2, 1) ...
// 曲线行驶 (3, 0) (3, 1) ...
// 侧方停车 (4, 0) (4, 1) ...
const startImage: Resource[] = [$rawfile("images/start.png"), $rawfile("images/finish.png"), $rawfile("images/finish.png")]
const resumeImage: Resource[] = [$rawfile("images/resume.png"), $rawfile("images/pause.png"), $rawfile("images/resume.png")]
const audios = new Array(33).map((_, i) => {
return "audio/output_" + i + ".mp3"
})
const projectAudio = [
[4, 5],
[0, 1, 2, 3],
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
[29, 30, 31, 32],
[22, 23, 24, 25, 26, 27, 28],
]
@Component
struct CustomButton {
@Prop checked: boolean
private text: string = ""
build() {
Button(this.text, { type: ButtonType.Normal })
.backgroundColor(this.checked ? 0xff5e69 : 0xffffff)
.fontColor(this.checked ? 0xffffff : 0x557685)
.borderRadius(8)
.shadow({
offsetX: 3,
offsetY: 3,
color: 0xf1f1f1,
radius: 10
})
.width("100%")
}
}
@Entry
@Component
struct Index {
@State status: Status = Status.Idle
@State paths: ConfigItemProps<Array<Array<number>>>[] = []
@State libraries: ConfigItemProps<Array<number>>[] = []
@State currentPath: number = 0
@State currentLibrary: number = 0
@State process: number = 1
private line: string
private lib: string
private carModel: string
private fieldModel: string
private teachPoint: string
private teachPointParams: string
private basePoint: string
private player: MediaPlayer = new MediaPlayer(getContext(this) as common.UIAbilityContext)
private simulatorUdpClient?: SimulatorUdpClient
private backupUdpClient?: BackMachineUdpClient
private outWireControl?: OutWireControl
private carStatus: number = 0
async aboutToAppear() {
try {
await this.initWireControlUDP()
await this.initPlatformUDP()
await this.initAudioPlayer()
await this.initBackMachineUDP()
await getConfigFile().then(([fieldModel, carModel, line, lib, teachPoint, teachPointParams, basePoint]) => {
this.fieldModel = fieldModel
this.carModel = carModel
this.teachPoint = teachPoint
this.basePoint = basePoint
this.teachPointParams = teachPointParams
this.line = line
this.lib = lib
this.libraries = (JSON.parse(lib) as ConfigProps<Array<number>>).features
this.paths = (JSON.parse(line) as ConfigProps<Array<Array<number>>>).features
})
await nativeSDKInit()
await nativeLogCallback((message: string, _: number) => {
LogHelper.I("NativeSDK", "[Log Callback]: ", message)
})
await registerControlCallback((fxp: number, move: number) => {
if (fxp > 0) {
this.outWireControl.rightWheel(fxp)
} else {
this.outWireControl.leftWheel(fxp)
}
switch (move) {
case -1000:
break;
case -1:
this.outWireControl.moveDown()
this.carStatus = move
break;
case 0:
this.outWireControl.moveStop()
this.carStatus = move
break;
case 1:
this.outWireControl.moveUp()
this.carStatus = move
break;
default:
break;
}
LogHelper.I("NativeSDK", "[Control Callback]: ")
})
await registerSoundCallback((project: number, idx: number) => {
this.playAudio(project, idx)
LogHelper.I("NativeSDK", "[Sound Callback]: ")
})
await setImageSize(500, 300)
await setConfigFile(this.basePoint, this.fieldModel, this.teachPoint, this.teachPointParams, this.carModel, this.line, this.lib)
} catch (err) {
promptAction.showToast({
message: JSON.stringify(err?.message || err),
duration: 3000
})
LogHelper.E("View", JSON.stringify(err?.message || err))
}
}
// 播放语音
async playAudio(project: number, idx: number) {
try {
await this.player.setSource({
type: "raw",
url: audios[projectAudio[project][idx]]
})
} catch (err) {
promptAction.showToast({
message: JSON.stringify(err?.message || err),
duration: 3000
})
LogHelper.E("View", JSON.stringify(err?.message || err))
}
}
// 初始化语音播放器
async initAudioPlayer() {
await this.player.create()
this.player.on("prepared", () => {
this.player.play()
})
}
// 初始化终端UDP
async initPlatformUDP() {
this.simulatorUdpClient = new SimulatorUdpClient("0.0.0.0", 8990, "88.22.10.118", 9001)
try {
await this.simulatorUdpClient.bindUdp()
// this.simulatorUdpClient.heart()
// setInterval(() => {
// this.simulatorUdpClient.uploadPosition(new GpsInfo(), new CarInfo())
// }, 1000)
this.simulatorUdpClient.onMessage(({type, data = [] }: MessageCallBackParams) => {
if (type === CommandType.Start) {
let path = this.paths.findIndex(item => {
return item.properties.id === data[0]
})
let lib = this.libraries.findIndex(item => {
return item.properties.id === data[1]
})
if (path === -1 || lib === -1) {
promptAction.showToast({
message: "错误的路线或库位"
})
this.simulatorUdpClient.sendPID26(CommandType.Failed)
return
}
this.currentPath = path
this.currentLibrary = lib
this.status = Status.Running
this.simulatorUdpClient.sendPID26(CommandType.Success)
}
else if (type === CommandType.Stop) {
this.status = Status.Idle
this.simulatorUdpClient.sendPID26(CommandType.Success)
}
})
} catch (err) {
throw new Error(JSON.stringify(err))
}
}
// 初始化后置机UDP
async initBackMachineUDP() {
this.backupUdpClient = new BackMachineUdpClient("0.0.0.0", 8991, "", 0)
try {
await this.backupUdpClient.bindUdp()
this.backupUdpClient.onMessage((arr) => {
let gps = parseGps(arr)
let car = parseCar(arr)
this.simulatorUdpClient?.uploadPosition(gps, car)
onTrack(gps.lng, gps.lat, gps.heading, gps.v)
})
} catch (err) {
throw new Error(JSON.stringify(err))
}
}
// 初始化车机控制UDP
async initWireControlUDP() {
this.outWireControl = new OutWireControl()
await this.outWireControl.init("192.168.7.181", 30021)
}
// 上方按钮点击
onConfirm() {
if (this.status === Status.Idle) {
this.simulatorUdpClient?.setPathId(this.paths[this.currentPath].properties.id)
this.simulatorUdpClient?.setLibId(this.libraries[this.currentLibrary].properties.id)
this.simulatorUdpClient?.sendPID26(CommandType.Start)
selectLineAndLib(this.paths[this.currentPath].properties.id, this.libraries[this.currentLibrary].properties.id)
this.status = Status.Running
this.outWireControl.apaStart()
} else {
this.simulatorUdpClient?.sendPID26(CommandType.Stop)
this.status = Status.Idle
this.outWireControl.moveStop()
this.outWireControl.apaStop()
}
}
// 下方按钮点击
onCancel() {
if (this.status === Status.Running) {
this.status = Status.Pause
this.outWireControl.moveStop()
} else if (this.status === Status.Pause) {
switch (this.carStatus) {
case -1:
this.outWireControl.moveDown()
break;
case 0:
this.outWireControl.moveStop()
break;
case 1:
this.outWireControl.moveUp()
break;
default:
break;
}
this.status = Status.Running
}
}
build() {
Row() {
Stack() {
RealTime()
Row() {
Column() {
Row() {
ForEach(["项目演示", "发车", "收车"], (item, index) => {
Text(item)
.padding(12)
.backgroundColor(this.process === index ? 0xff5d69 : "rgba(240, 242, 246, 0.88)")
.fontColor(this.process === index ? 0xffffff : 0x7f899f)
.borderRadius(index === 0 ? { topLeft: 10, bottomLeft: 10 } : index === 2 ? {
topRight: 10,
bottomRight: 10
} : {})
.width(90)
.textAlign(TextAlign.Center)
.onClick(() => {
if (index > 0) {
this.process = index
}
})
})
}.borderRadius(10).margin({ bottom: 20 })
Column() {
Column() {
Row() {
Image($rawfile("images/path.png")).width(42)
Text("线路选择").fontColor(0x557685)
}.margin({ bottom: 12 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.paths, (item: ConfigItemProps<Array<Array<number>>>, index: number) => {
Row() {
CustomButton({ text: item.properties.name, checked: this.currentPath === index }).onClick(() => {
this.currentPath = index
}).margin({ bottom: 12 }).width("100%")
}.width("50%").padding({ left: index % 2 === 0 ? 0 : 5, right: index % 2 === 0 ? 5 : 0 })
})
}
}.alignItems(HorizontalAlign.Start).width("100%")
Column() {
Row() {
Image($rawfile("images/park.png")).width(42)
Text("库位选择").fontColor(0x557685)
}.margin({ bottom: 12 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.libraries, (item: ConfigItemProps<Array<number>>, index: number) => {
Row() {
CustomButton({ text: item.properties.name, checked: this.currentLibrary === index })
.onClick(() => {
this.currentLibrary = index
})
.margin({ bottom: 12 })
.width("100%")
}.width("50%").padding({ left: index % 2 === 0 ? 0 : 5, right: index % 2 === 0 ? 5 : 0 })
})
}
}.alignItems(HorizontalAlign.Start).width("100%")
}.backgroundColor("rgba(240, 242, 246, 0.88)").borderRadius(10).padding(12).width(270)
}
Blank()
Column() {
Image(startImage[this.status]).width(74).onClick(() => {
this.onConfirm()
})
Image(resumeImage[this.status]).width(74).onClick(() => {
this.onCancel()
})
}.backgroundColor('rgba(228, 229, 233, 0.7)').borderRadius(10)
}.width("100%").height("100%").padding(24).alignItems(VerticalAlign.Top)
}.height('100%')
.width("100%")
}
.height('100%')
.width("100%")
}
}