feat:新科目三开发

This commit is contained in:
Surenjun 2025-08-27 13:50:20 +08:00
parent 4c6f25ee3a
commit b5c641c16b
11 changed files with 378 additions and 10 deletions

View File

@ -0,0 +1,72 @@
import UdpClient from './udpClient/index'
import FileUtil from '../../common/utils/File';
import { GlobalConfig } from '../../config/index';
import emitter from '@ohos.events.emitter';
interface messageIds {
[k:string]:number;
}
class Lidar {
public localRadarUdp: UdpClient
public localVisionUdp: UdpClient
private isNewKm3: Boolean
private messageIds:messageIds = {}
constructor() {
this.init()
}
//监听雷达信息
async onRadarMsg(messageId:string,callback:Function) {
if(this.messageIds[messageId] === undefined){
let timer = setInterval(()=>{
callback(this.radarObj)
},200)
this.messageIds[messageId] = timer;
}
}
//监听视觉信息
async onSenseMsg(messageId:string,callback:Function) {
if(this.messageIds[messageId] === undefined){
let timer = setInterval(()=>{
callback(this.senseObj)
},200)
this.messageIds[messageId] = timer;
}
}
//关闭消息
async offVisionMsg(eventId) {
clearInterval(this.messageIds[eventId])
delete this.messageIds[eventId]
}
async init() {
const fileUtil = new FileUtil(globalThis.context)
const addressStr = await fileUtil.readFile(GlobalConfig.comoonfileWriteAddress + '/config/ipConfig.txt');
const {deviceType,deviceIpArr,devicePortArr,udplocalIp} = JSON.parse(addressStr);
//新科目三设备
if (deviceType == '2') {
//雷达数据
this.localRadarUdp = new UdpClient('radar', {
deviceIpArr, devicePortArr, udplocalIp
});
//视觉数据
this.localVisionUdp = new UdpClient('vision', {
deviceIpArr, devicePortArr, udplocalIp
})
this.localRadarUdp.onMessage((obj) => {
this.radarObj = obj
})
this.localVisionUdp.onMessage((obj) => {
this.visionObj = obj
})
this.isNewKm3 = true;
}
}
}

View File

@ -0,0 +1,10 @@
export default class SenseUtil{
constructor() {}
//扣分
//开始考试
//结束考试
}

View File

@ -0,0 +1,112 @@
import socket from '@ohos.net.socket';
import FileUtil from '../../../common/utils/File';
import { GlobalConfig } from '../../../config/index';
import promptAction from '@ohos.promptAction'
const TAG = 'LIDAUDP'
type TYPE = 'vision' | 'radar'
interface IPAPORT{
address:string,
port:number
}
interface Params{
deviceIpArr:string[],
devicePortArr:number[],
udplocalIp:string
}
export default class LidaUdpClient{
// 0: 视觉 1: 雷达
public type:TYPE
private udpClient:socket.UDPSocket
private localIp:string
private localSensePort: 33313
private localVisionPort: 33314
private params:Params
public message:string
constructor(type:TYPE,params:Params) {
this.type = type;
this.params = params
this.localIp = params.udplocalIp
}
async init(){
const {address,port} = await this.getIpAPort()
this.udpClient = socket.constructUDPSocketInstance();
//bind
await this.safeFn(async()=>{
await this.udpClient.bind({
address: this.localIp,
port: port,
family: 1
});
})
}
async onMessage(callback){
this.offMessage()
//message
this.udpClient.on('message',(val)=>{
//TODO 消息解析
switch (this.type){
//激光雷达
case 'radar':
this.radarStrToObj(val)
break;
//视觉
case 'vision':
this.visionStrToObj(val)
break;
}
console.log(val+'');
});
}
//获取对应的IP和端口
async getIpAPort(): Promise<IPAPORT>{
const fileUtil = new FileUtil(globalThis.context)
const addressStr = await fileUtil.readFile(GlobalConfig.comoonfileWriteAddress + '/config/ipConfig.txt');
const {deviceIpArr,devicePortArr,udplocalIp} = JSON.parse(addressStr);
this.localIp = udplocalIp
return {
address:this.type === 'radar' ? deviceIpArr[0] : deviceIpArr[1],
port: Number(this.type === 'vision' ? devicePortArr[1] : devicePortArr[1])
}
}
//
async radarStrToObj(str:string){
//$MachineVision,30.950^0_-1_1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1^-1,43083,0_0_0_0,-1^-1_-1_-1_1,-1^-1_-1_-1_1,-1^-1_-1_-1_1,10102264201.69632,1.1.1.2,0*+$VisualInfo,1_-7205_3480_-7300_3350_-7655_3610_-7560_3735_,*+[ { "bodyangle": "1.00", "bodyx": "0.490", "bodyy": "31.300", "elevation": "2.403", "geoangle": "323.90", "geolat": "29.92678975", "geolon": "119.89823128", "id": 1, "type": 2 } ]
}
async visionStrToObj(str:string){
}
async offMessage(){
this.udpClient.off('message')
}
async closeUdp(){
this.offMessage();
this.udpClient.close()
}
async safeFn(fn:Function){
try {
await fn()
} catch (e) {
console.info(TAG + JSON.stringify(e))
promptAction.showToast({
message: TAG + JSON.stringify(e),
duration: 3000
});
throw e
}
}
}

View File

@ -218,6 +218,7 @@ export async function takePhoto(param, context, dir, flag = 1, callback?) {
// @ts-ignore // @ts-ignore
// var snapResult = rtsp_server.getVideoSnapshot(context, video_uri, '', dir); // var snapResult = rtsp_server.getVideoSnapshot(context, video_uri, '', dir);
if (flag == 0) { if (flag == 0) {
//@ts-ignore
rtsp_server.detectVideoSnapshotSize(video_uri, fileName, (err, snapResult) => { rtsp_server.detectVideoSnapshotSize(video_uri, fileName, (err, snapResult) => {
console.log("baohaowen_detectLoop round end size1:" + snapResult.fileSize); console.log("baohaowen_detectLoop round end size1:" + snapResult.fileSize);
callback({ fileSize: snapResult.fileSize, errorCode: snapResult.errorCode }) callback({ fileSize: snapResult.fileSize, errorCode: snapResult.errorCode })

View File

@ -85,3 +85,7 @@ export const RoadData = [
{name:'形状',key:['InShapeAttr','ShapeNo','']}, {name:'形状',key:['InShapeAttr','ShapeNo','']},
{name:'路段点',key:['CrossPointNo']}, {name:'路段点',key:['CrossPointNo']},
] ]
export const radarData = [
]

View File

@ -1121,6 +1121,9 @@ struct Index {
case '4': case '4':
return '#FF7566'; return '#FF7566';
break; break;
case '5':
return '#FF7566';
break;
default: default:
return '#E6DECF'; return '#E6DECF';
break; break;

View File

@ -23,10 +23,15 @@ struct Index {
@State terTextList: string[] = ['一型机', '二型机', '三型机', '一体机'] @State terTextList: string[] = ['一型机', '二型机', '三型机', '一体机']
@State cardTextList: string[] = ['北云', '天宝MB2'] @State cardTextList: string[] = ['北云', '天宝MB2']
@State netTextList: string[] = ['否', '是'] @State netTextList: string[] = ['否', '是']
@State deviceTypeSelect: string[] = ['正常', '安全员','新科目三']
@State selectedTerType: number = 0 @State selectedTerType: number = 0
@State selectedCardType: number = 0 @State selectedCardType: number = 0
//是否启用网络差分 //是否启用网络差分
@State netOpen: number = 0 @State netOpen: number = 0
//设备应用类型
@State deviceType: number = 0
@State deviceIpArr: string[] = ['192.168.7.173', '192.168.7.173']
@State devicePortArr: string[] = ['8052', '8053']
// @State inputTextList2: string[] = [] // @State inputTextList2: string[] = []
// 112.80.35.83 11052 // 112.80.35.83 11052
// @State inputTextList1: string[] = ['192.168.36.2','8084','192.168.36.200','20122','255.255.255.0','192.168.36.1','','','114.114.114.114','192.168.36.139','8000'] // @State inputTextList1: string[] = ['192.168.36.2','8084','192.168.36.200','20122','255.255.255.0','192.168.36.1','','','114.114.114.114','192.168.36.139','8000']
@ -118,7 +123,6 @@ struct Index {
}) })
}.width('51%').height('14%') }.width('51%').height('14%')
Row(){ Row(){
Text('板卡类型') Text('板卡类型')
.width('40%') .width('40%')
@ -140,6 +144,124 @@ struct Index {
}) })
}.width('49%').height('14%') }.width('49%').height('14%')
Row() {
Text('设备应用场景')
.width('40%')
.height('100%')
.fontColor('#E5CBA1')
.padding({ 'left': '35px' })
.fontSize(this.inputFontSize * this.ratio)
ForEach(this.deviceTypeSelect, (netText, index) => {
Radio({ value: netText, group: 'deviceRadioGroup' })
.borderColor('#E5CBA1')
.checked(index === this.deviceType)
.onChange((value: boolean) => {
if(value){
this.deviceType = index
}
})
Text(netText).fontSize(20).fontColor('#FFF')
})
}.width('52%').height('14%')
if(this.deviceType == 2){
Row() {
Text('雷达设备IP')
.width('40%')
.height('100%')
.fontColor('#E5CBA1')
.padding({ 'left': '35px' })
.fontSize(this.inputFontSize * this.ratio)
TextInput({ 'text':this.deviceIpArr[0] })
.width('50%')
.height('50%')
.fontColor('#fff')
.borderColor('#E6E0D8')
.borderRadius('10px')
.borderWidth('2px')
.fontSize(this.inputFontSize * this.ratio)
.padding({ top: 0, bottom: 0 })
.linearGradient({angle: 0,colors: [[0x403C36, 0.0], [0x4D473D, 0.34], [0x3D3A34, 1.0]] })
.onChange((value: string) => {
this.deviceIpArr[0] = value
})
}.width('50%').height('14%')
Row() {
Text('响应端口')
.width('40%')
.height('100%')
.fontColor('#E5CBA1')
.padding({ 'left': '35px' })
.fontSize(this.inputFontSize * this.ratio)
TextInput({ 'text':this.devicePortArr[0] })
.width('50%')
.height('50%')
.fontColor('#fff')
.borderColor('#E6E0D8')
.borderRadius('10px')
.borderWidth('2px')
.fontSize(this.inputFontSize * this.ratio)
.padding({ top: 0, bottom: 0 })
.linearGradient({
angle: 0,
colors: [[0x403C36, 0.0], [0x4D473D, 0.34], [0x3D3A34, 1.0]]
})
.onChange((value: string) => {
this.devicePortArr[0] = value
})
}.width('50%').height('14%')
Row() {
Text('视觉设备IP')
.width('40%')
.height('100%')
.fontColor('#E5CBA1')
.padding({ 'left': '35px' })
.fontSize(this.inputFontSize * this.ratio)
TextInput({ 'text': this.deviceIpArr[1] })
.width('50%')
.height('50%')
.fontColor('#fff')
.borderColor('#E6E0D8')
.borderRadius('10px')
.borderWidth('2px')
.fontSize(this.inputFontSize * this.ratio)
.padding({ top: 0, bottom: 0 })
.linearGradient({
angle: 0,
colors: [[0x403C36, 0.0], [0x4D473D, 0.34], [0x3D3A34, 1.0]]
})
.onChange((value: string) => {
this.deviceIpArr[1] = value
})
}.width('50%').height('14%')
Row() {
Text('响应端口')
.width('40%')
.height('100%')
.fontColor('#E5CBA1')
.padding({ 'left': '35px' })
.fontSize(this.inputFontSize * this.ratio)
TextInput({ 'text': this.devicePortArr[1] })
.width('50%')
.height('50%')
.fontColor('#fff')
.borderColor('#E6E0D8')
.borderRadius('10px')
.borderWidth('2px')
.fontSize(this.inputFontSize * this.ratio)
.padding({ top: 0, bottom: 0 })
.linearGradient({
angle: 0,
colors: [[0x403C36, 0.0], [0x4D473D, 0.34], [0x3D3A34, 1.0]]
})
.onChange((value: string) => {
this.devicePortArr[1] = value;
})
}.width('50%').height('14%')
}
} }
} }
.width('95%') .width('95%')
@ -172,7 +294,10 @@ struct Index {
centerPort: this.inputTextList1[3], centerPort: this.inputTextList1[3],
terType: this.selectedTerType, terType: this.selectedTerType,
cardType: this.selectedCardType, cardType: this.selectedCardType,
netOpen: this.netOpen netOpen: this.netOpen,
deviceType: this.deviceType,
deviceIpArr: this.deviceIpArr,
devicePortArr: this.devicePortArr,
} }
fileUtil.addFile(`${folderPath}/ipConfig.txt`, JSON.stringify(param), '') fileUtil.addFile(`${folderPath}/ipConfig.txt`, JSON.stringify(param), '')
// upDateTableByArray('IpConfigTable',[]) // upDateTableByArray('IpConfigTable',[])
@ -247,6 +372,9 @@ struct Index {
this.selectedTerType = result.terType this.selectedTerType = result.terType
this.selectedCardType = result.cardType this.selectedCardType = result.cardType
this.netOpen= result.netOpen this.netOpen= result.netOpen
this.deviceType= result.deviceType || 0
this.deviceIpArr= result.deviceIpArr || ['','']
this.devicePortArr= result.devicePortArr || ['','']
console.log('surenjun', this.selectedTerType + ''); console.log('surenjun', this.selectedTerType + '');
} }

View File

@ -69,6 +69,18 @@ export default struct SignDisplayCom {
}) })
} }
Row() {
Text('雷达数据').fontColor(this.active == 3 ? '#FFAD33' : '#e7cba3').fontSize(20 * this.ratio)
}
.backgroundImage(this.active == 3 ? $r('app.media.signal_tabS') : $r('app.media.signal_tab'))
.width(144 * this.ratio)
.height(50 * this.ratio)
.backgroundImageSize({ width: '100%', height: '100%' })
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.active = 3
})
Row() { Row() {
Text('原始数据').fontColor(this.active == 2 ? '#FFAD33' : '#e7cba3').fontSize(20 * this.ratio) Text('原始数据').fontColor(this.active == 2 ? '#FFAD33' : '#e7cba3').fontSize(20 * this.ratio)
} }
@ -314,6 +326,30 @@ export default struct SignDisplayCom {
.backgroundImage($r('app.media.km_open')) .backgroundImage($r('app.media.km_open'))
.backgroundImageSize({ width: '100%', height: '100%' }) .backgroundImageSize({ width: '100%', height: '100%' })
.visibility(this.active == 1 ? Visibility.Visible : Visibility.None) .visibility(this.active == 1 ? Visibility.Visible : Visibility.None)
Row(){
Column() {
Column(){
Text('雷达').fontColor('#fff')
}
Column(){
Text('视觉').fontColor('#fff')
}
.height(436 * this.ratio)
}
.backgroundColor('#282828')
.width(this.ratio * 880)
.height(415 * this.ratio)
.margin({ left: 15 * this.ratio, top: 15 * this.ratio })
}
.width(936 * this.ratio)
.height(460 * this.ratio)
.margin({ left: 10 * this.ratio })
.padding({ left: 10 * this.ratio, right: 10 * this.ratio })
.backgroundImage($r('app.media.km_open'))
.backgroundImageSize({ width: '100%', height: '100%' })
.visibility(this.active == 3 ? Visibility.Visible : Visibility.None)
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
@ -323,6 +359,8 @@ export default struct SignDisplayCom {
aboutToDisappear() { aboutToDisappear() {
clearInterval(this.interval) clearInterval(this.interval)
//TODO
console.info('surenjun','123')
} }
async aboutToAppear() { async aboutToAppear() {

View File

@ -44,7 +44,7 @@ export default struct RealTime {
Row() { Row() {
Column() { Column() {
Row() { Row() {
Text('车道信息').fontColor(this.gpsActive == 0 ? '#2D3C5A' : '#fff').fontSize(20) Text('车道信息').fontColor(this.gpsActive == 0 ? '#2D3C5A' : '#fff').fontSize(14)
} }
.width('100%') .width('100%')
.height(37) .height(37)

View File

@ -934,6 +934,8 @@ export default class Judge {
this.judgeUI.totalScore += thisKf.score * 1; this.judgeUI.totalScore += thisKf.score * 1;
if (kf.xmdm != 20) { if (kf.xmdm != 20) {
const type = judgeUI.projectsObj[kf.xmdm].type; const type = judgeUI.projectsObj[kf.xmdm].type;
console.info('surejun kf=>',JSON.stringify(kf))
console.info('surejun kf_type=>',type)
judgeUI.projectsObj[kf.xmdm].type = (type == 3 || type == 4) ? '4' : '5'; judgeUI.projectsObj[kf.xmdm].type = (type == 3 || type == 4) ? '4' : '5';
} }
break; break;
@ -956,11 +958,11 @@ export default class Judge {
console.info(judgeTag, '项目取消'); console.info(judgeTag, '项目取消');
const {examSubject} = this.judgeUI const {examSubject} = this.judgeUI
const xmdm = xmqx.xmdm; const xmdm = xmqx.xmdm;
const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; const xmmcCode1 = judgeUI.projectsObj[xmdm].projectCodeCenter;
// const voiceCode = getKmProjectCancelVoice(examSubject, xmmcCode); // const voiceCode = getKmProjectCancelVoice(examSubject, xmmcCode);
// avPlayer.playAudio([`voice/${voiceCode}.mp3`],true) // avPlayer.playAudio([`voice/${voiceCode}.mp3`],true)
this.judgeUI.projectsObj[xmdm].type = '1'; this.judgeUI.projectsObj[xmdm].type = '1';
this.testKmItems[xmmcCode].status = '1'; this.testKmItems[xmmcCode1].status = '1';
break; break;
} }

View File

@ -2,9 +2,9 @@
export const judgeConfig = { export const judgeConfig = {
version:'2024.08.21.01', version:'2024.08.21.01',
//本地目录开关 //本地目录开关
isTrajectoryOpen: false, isTrajectoryOpen: true,
//是否开启拍照 //是否开启拍照
isPhotoOpen: true, isPhotoOpen: false,
//扣分语音是否强制开启 //扣分语音是否强制开启
kfVoiceOpen: false, kfVoiceOpen: false,
//忽略的考试项目 //忽略的考试项目
@ -16,14 +16,12 @@ export const judgeConfig = {
// 本地模型地址 // 本地模型地址
// modelPath: 'models/model_enc', // modelPath: 'models/model_enc',
// 济南科目三 // 济南科目三
trajectoryPath: 'logs/2025_04_23_09_50_55_2504755332926_320924199111132926_陈静/judge_exam_data.txt', trajectoryPath: 'logs/2025_06_20_08_20_09_2250107217821_340823199508126112_左江辉/judge_exam_data.txt',
//四合一画面配置 //四合一画面配置
fourInOneScreen:{ fourInOneScreen:{
//gps位数 //gps位数
gpsDigit:7 gpsDigit:7
}, },
// 杭州科目二
// trajectoryPath: 'logs/2024_07_19/0000000000001_342323199501470011_测试学员1_2024_07_19_06_49_12/judge_exam_data.txt',
//TODO 济南临时特殊配置 //TODO 济南临时特殊配置
systemParamConfig:{} systemParamConfig:{}
} }