360 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			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%")
 | |
|   }
 | |
| } |