From 577083362194a2f7120e83b3fb41425c292e1444 Mon Sep 17 00:00:00 2001 From: lvyuankang <1344032923@qq.com> Date: Wed, 10 Jul 2024 14:09:42 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/ets/pages/judgeSDK/utils/fileLog.ts | 117 ++++++ .../ets/pages/judgeSDK/utils/fileModel.ts | 54 +++ .../ets/pages/judgeSDK/utils/filePhoto.ts | 71 ++++ .../ets/pages/judgeSDK/utils/judgeCommon.ts | 397 ++++++++++++++++++ .../ets/pages/judgeSDK/utils/judgeConfig.ts | 17 + .../ets/pages/judgeSDK/utils/judgeReal.ts | 48 +++ .../ets/pages/judgeSDK/utils/judgeTask.ts | 42 ++ .../judgeSDK/utils/voiceAnnouncements.ts | 150 +++++++ 8 files changed, 896 insertions(+) create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts diff --git a/entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts b/entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts new file mode 100644 index 00000000..8cbf69b2 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts @@ -0,0 +1,117 @@ +import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl' +import promptAction from '@ohos.promptAction' +import fileAccess from '@ohos.file.fileAccess' +import common from '@ohos.app.ability.common' +import Want from '@ohos.app.ability.Want' +import fs from '@ohos.file.fs' +import FileUtil from '../../../common/utils/File' +import {getCurrentTime} from '../../../common/utils/tools' + +interface StuInfo{ + name:string + lsh:string + idCard:string +} + +const LOGTAG = 'LOGTAG' +export default class FileLog { + + //后续文件路径待替换 + private fileUtil: FileUtil + private stuInfo: StuInfo + public folderPath: string + + constructor(context) { + const fileUtil = new FileUtil(context) + this.fileUtil = fileUtil + } + + // 设置文件夹 + public initFileLogo = async (stuInfo:StuInfo) => { + const {fileUtil,setExamLineData} = this + const {name,lsh,idCard} = stuInfo; + this.stuInfo = stuInfo; + const time = await getCurrentTime() + const date = time.split(' ')[0].split('-').join('_') + const hourTime = time.split(' ')[1].split(':').join('_') + const folderPath = await fileUtil.initFolder(`/logs/${date}/${lsh}_${idCard}_${name}_${date}_${hourTime}`); + this.folderPath = folderPath; + } + + // 过程文件数据 + public setExamProgressData = async (str:Object) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/exam_progress_data.txt`,JSON.stringify(str)); + } + + // 无锡所接口数据 + public setExamJudgeWuxiData = async (str) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/wuxi_exam_data.txt`,str); + } + + // 无锡所过程数据 + public setExamJudgeWuxiProgressData = async (str)=>{ + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/wuxi_progress_data.txt`,str); + } + + // plc文件数据 + public setPlcProgressData = async (str:Object) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/plc_data.txt`,JSON.stringify(str)); + } + + // 过程评判json数据 + public setExamJudgeData = async (str:Object) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/judge_exam_data.txt`,JSON.stringify(str)); + } + + // 过程评判回调数据 + public setExamJudgeCallbackData = async (str:string) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/judge_progress_callback_data.txt`,str); + } + + // 过程评判日志调数据 + public setExamJudgeLogData = async (str:string) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/judge_log_data.txt`,str); + } + + // 无锡所轨迹数据 + public setExamLineData = async (plcStr) => { + const {fileUtil,folderPath} = this; + const plcData = plcStr.split(','); + const time = await getCurrentTime(); + + const lineData = [ + /*帧头*/ time, + /*卫星时间*/time, + /*经度*/ plcData[95], + /*纬度*/ plcData[95], + /*高度*/ plcData[86], + /*方位角*/ 0, + /*俯仰角*/ plcData[91], + /*速度角*/'', + /*速度*/ plcData[97], + /*横滚*/'', + /*卫星定位状态*/'', + /*卫星定向状态*/'', + /*前天线可用星数*/'', + /*后天线可用星数*/'', + /*东向位置坐标*/'', + /*北向位置坐标*/'', + /*天向位置坐标*/'', + /*东向速度*/'', + /*北向速度*/'', + /*评判信号1*/[plcData[14],plcData[19],plcData[5],'',plcData[2],plcData[3],plcData[7],plcData[8],plcData[13],plcData[12],plcData[17],'',plcData[4],plcData[11],plcData[20],plcData[9],0].join(','), + /*评判信号2*/['',plcData[28],'','',plcData[10],'','','','','','','','','','','','',''].join(','), + /*发动机转速*/ plcData[25], + /*结束符*/ time, + ]; + + await fileUtil.editFile(`${folderPath}/exam_wuxi_data.txt`,JSON.stringify(lineData)); + }; +} diff --git a/entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts b/entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts new file mode 100644 index 00000000..a935a7fd --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts @@ -0,0 +1,54 @@ +import FileUtil from '../../../common/utils/File' +import zlib from '@ohos.zlib'; +export default class FileModel{ + + //后续文件路径待替换 + private fileUtil: FileUtil + public folderPath: string + + constructor(context){ + (async ()=>{ + const fileUtil = new FileUtil(context) + this.fileUtil = fileUtil + })() + + } + + // 设置文件夹 + public initFolder = async () => { + const {fileUtil} = this + await fileUtil.initFolder(`/models/model_enc`); + const folderPath = await fileUtil.initFolder(`/models`); + this.folderPath = folderPath; + } + + // 存储zip文件并解压 + public storingFiles = async (str) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/model.zip`,str,'overWrite') + + let options = { + level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION, + memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT, + strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY + }; + + zlib.unzipFile( + `${folderPath}/model.zip`, + `${folderPath}`, + options).then((data) => { + console.log("unzipFile result:" + data); + }).catch((err)=>{ + console.log("catch((err)=>" + err); + }) + + } + + //获取文件内容 + public getModelContent = (folderPath,fileName) => { + const {fileUtil} = this; + const content = fileUtil.getFileContent(`${folderPath}/${fileName}`) + return content; + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts b/entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts new file mode 100644 index 00000000..58aac620 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts @@ -0,0 +1,71 @@ +import mediaLibrary from '@ohos.multimedia.mediaLibrary' +import onvifclient from '@ohos.onvifclient'; +import fs from '@ohos.file.fs' +import util from '@ohos.util'; +import FileUtil from '../../../common/utils/File' + +interface Params{ + userName:string + pwd:string + ip:string + port:string + rlls:string +} + +export default class FilePhoto{ + + private params:Params + private context:any + private fileUtil:FileUtil + public mediaTest + + constructor(context) { + (async ()=>{ + const fileUtil = new FileUtil(context) + const strConfig = await fileUtil.readFile('/mnt/hmdfs/100/account/device_view/local/files/logs/config/config3.txt'); + const config = JSON.parse(strConfig) + const {userName,ip,pwd,port,rlls} = config + this.params = {userName,pwd,ip,port,rlls} + this.context = context + this.fileUtil = fileUtil + })() + } + + public async getPhoto(){ + const {params,context,fileUtil} = this; + const {userName,pwd,ip,port,rlls} = params; + const mediaTest = mediaLibrary.getMediaLibrary(context); + let mediaType = mediaLibrary.MediaType.IMAGE; + let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_IMAGE; + const path = await mediaTest.getPublicDirectory(DIR_DOCUMENTS); + + return new Promise(async (resolve)=>{ + mediaTest.createAsset(mediaType, 'judge_face.jpg', path,(error,asset)=>{ + asset.open('rw', (error, fd) => { + if (fd > 0) { + const file_path = "/mnt/hmdfs/100/account/device_view/local/files/Pictures/judge_face.jpg" + const result3 = onvifclient.getVideoSnapshot(`rtsp://${userName}:${pwd}@${ip}:${port}/h264/ch${rlls}/main/av_stream`,file_path,fd); + fs.closeSync(fd); + asset.close(fd); + fs.lstat(file_path).then((stat) => { + console.info("get link status succeed, the size of file is" + stat.size); + let file = fs.openSync(file_path, fs.OpenMode.READ_WRITE); + const size=Number(stat.size)+100 + let buf = new ArrayBuffer(size); + let num = fs.readSync(file.fd, buf); + const that = new util.Base64(); + const array = new Uint8Array(buf); + const result = that.encodeToStringSync(array);//base64圖片 + fileUtil.deleteF(file_path,3) + resolve(result) + }).catch((err) => { + console.info("get link status failed with error message: " + err.message + ", error code: " + err.code); + }); + } else { + console.error('baoyihu getVideoSnapshot File Open failed with error: ' + error); + } + }); + }); + }) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts new file mode 100644 index 00000000..fafeaeca --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts @@ -0,0 +1,397 @@ +import {string2Bytes,Array2Byte,getCurrentTime} from '../../../common/utils/tools' +import {testMarkRules,testRealExam,testKmItems} from '../dataTest/index' + +import promptAction from '@ohos.promptAction' +import systemTime from '@ohos.systemDateTime'; + +//获取本地扣分项 +export const getTestMarkRules = () =>{ + testMarkRules.map((mark:any) => { + return { + itemno:mark.itemno*1, + markcatalog:mark.markcatalog, + markshow:mark.markshow, + markreal:mark.markreal*1, + markserial:mark.markserial, + kfxh:mark.kfxh + } + }) +} + +// 中心信号转换 +export const getTranslateSignals = (tempItems) => { + const len = Math.floor(tempItems.length / 8); + const arr = []; + for(let i = 0;i < len;i++){ + const temp = tempItems.slice( i*8 , (i+1)*8 ); + arr.push(temp.join('')); + } + const temp = arr.map(numStr => parseInt(numStr,2)) + return temp.map(item => string2Bytes(item , 8)[0]) +} + +// c++评判考车行驶状态转换 +export function getCarStatus(status: -1 | 0 | 1):string { + switch (status){ + case -1:return '后退' + case 0:return '停车' + case 1:return '前进' + default :return '' + } +} + +// 当前考车中心状态转换 +export function getCarStatusType(carzt){ + switch (carzt){ + case -1:return [1,0] + case 0: return [0,0] + case 1: return [0,1] + } +} + + +// 中心实时项目状态转换 +export function getCenterProjectStatus(status){ + switch (status){ + //不考 + case 0:return '00' + //未考 + case 1:return '01' + //已考 + case 2:return '10' + } +} + +//获取科目三开始项目、结束项目语音 + +export function getKmProjectVoice( + projectCode, + // 1:项目开始 2:项目结束 + type: 1 | 2 +) { + const carInfo = globalThis.carInfo; + const { examSubject } = carInfo; + + if(examSubject == 2){ + return projectCode + } + + switch (projectCode*1){ + //直线行驶 + case 40300: return type === 1 ? 403001 : 403002 + //变更车道 + case 40500: return type === 1 ? 405001 : 405002 + //超车 + case 41400 : return type === 1 ? 414001 : undefined + //直线行驶 + case 40700 : return type === 1 ? 407001 : undefined + //左转 + case 40800 : return type === 1 ? 408001 : undefined + //右转 + case 40900 : return type === 1 ? 409001 : undefined + //通过人行横道 + case 41000 : return type === 1? 410001:undefined + //通过学校 + case 41100 : return type === 1 ? 411001:undefined + //通过车站 + case 41200 : return type === 1 ? 412001 : undefined + //会车 + case 41300 : return type === 1 ? 413001: 413002 + //靠边停车 + case 40600 : return type === 1 ? 406001 : undefined + //掉头 + case 41500 : return type === 1 ? 415001:undefined + //超车 + case 40400 : return type === 1 ? 404001:undefined + + default :return undefined + } + +} + +// 上传监管数据code转换 +export function promptWxCode( + jkid:'17C52' | '17C54' |'17C55' | '17C53' | '17C56', + code:number +){ + let toast = ''; + const singlePlay = globalThis.singlePlay + if(singlePlay){ + return + } + switch (jkid){ + //项目开始 + case '17C52': + switch (code){ + case 0:toast = '存在作弊嫌疑,已被取消或暂停考试';break; + case -1:toast = '无考生身份比对信息';break; + case -2:toast = '考试项目与考试安排信息不符';break; + case -3:toast = '考试设备未备案';break; + case -4:toast = '考试设备与考试项目不符';break; + case -5:toast = '考试设备使用状态异常';break; + case -6:toast = '考生考试车型与考试设备使用准驾车型范围不符';break; + case -7:toast = '该考生存在作弊嫌疑,已被暂停/取消考试';break; + case -8:toast = '项目开始时间不能小于科目开始时间';break; + case -9:toast = '存在未结束的考试项目、不能开始新的项目考试!';break; + case -10:toast = '科目三考车号牌不能为空';break; + case -11:toast = '同一考车存在未结束考试,不能开始应用于新的考试';break; + case -12:toast = '未找到考场记录';break; + case -13:toast = '未找到考车信息';break; + case -14:toast = '随机抽取考生的考车与当前考车不一致';break; + default:toast = '';break; + } + break; + //过程照片 + case '17C54': + switch (code){ + case -1:toast = '无当前科目考试信息';break; + case -2:toast = '考生身份证明号码与考生预约信息不符';break; + case -3:toast = '考试项目不正确';break; + case -4:toast = '考试过程中拍摄照片数量少于3张!';break; + case -5:toast = '考试项目不符合要求';break; + case -6:toast = '存在未结束的考试项目!';break; + } + break; + //项目结束 + case '17C55': + switch (code){ + case -1:toast = '无当前考试项目开始信息';break; + case -2:toast = '考生身份证明号码与考生预约信息不符';break; + case -3:toast = '考试项目不正确';break; + case -4:toast = '考试设备序号不正确!';break; + case -5:toast = '考试项目结束时间写入错误';break; + case -6:toast = '考生未进行身份认证';break; + case -7:toast = '项目考试过程信息记录被非法篡改';break; + case -8:toast = '每个考试项目中必须至少抓拍一张照片';break; + case -12:toast = '未找到考场记录';break; + case -13:toast = '未找到考车信息';break; + case -15:toast = '考试过程信息必须由考车上传';break; + case -90:toast = '考试项目已经结束、无需重传';break; + case -91:toast = '实际道路考试,在完成科目考试时统一结束';break; + default:break; + } + break; + //扣分 + case '17C53': + switch (code){ + case 0:toast = '已存在同一时间的同一扣分记录';break + case -1:toast = '无当前考试项目开始信息';break; + case -2:toast = '扣分时间大于项目开始时间!';break; + case -3:toast = '考试项目与扣分项不符';break; + case -4:toast = '项目考试过程中,请传入当前考试项目代码';break; + case -5:toast = '考生未进行身份认证';break; + case -6:toast = '扣分时间写入错误';break; + case -7:toast = '项目考试过程信息记录被非法篡改';break; + case -12:toast = '未找到考场记录';break; + case -13:toast = '未找到考车信息';break; + case -15:toast = '考试过程信息必须由考车上传';break; + default:toast = '';break + } + break; + //考试结束 + case '17C56': + switch (code){ + case -1:toast = '无当前科目考试信息';break; + case -2:toast = '考生身份证明号码与考生预约信息不符';break; + case -3:toast = '考试结束时间不正确';break; + case -4:toast = '考试过程中拍摄照片数量少于3张!';break; + case -5:toast = '考试项目不符合要求';break; + case -6:toast = '存在未结束的考试项目!';break; + case -7:toast = '传输的考试成绩非空';break; + case -91:toast = '考试成绩计算不一致';break; + case -91:toast = '日间考试已结束等待进行夜间考试';break; + default: toast = '';break + } + break; + default :break; + } + promptAction.showToast({ + message: decodeURIComponent(toast), + duration: 4000 + }); +} + +// 获取plc数据 +export const plcStrToJson = async (plc:string) =>{ + + const p = plc.split(',').map((val,key)=>{ + if(key !== 27 && key !== 92){ + //@ts-ignore + return val*1 + }else{ + return val + } + }); + let data:any = testRealExam; + const time = await systemTime.getCurrentTime() + const tempData = { + sensor:{ + //安全带 车门门开关 手刹 脚刹 副刹 离合器 喇叭 示宽灯 近光灯 远光灯 + aqd:p[19], mkg:p[14], ssc:p[13], jsc:p[12], fsc:p[18], lhq:p[17], lb:p[4], skd:p[9], jgd:p[7], ygd:p[8], + //左方向灯 右方向灯 双跳灯 雾灯 雨刮器 点火1 点火2 发动机转速 档位 车速 + zfxd:p[2], yfxd:p[3], shtd:p[20],wd:p[10], ygq:p[11], dh1:p[5], dh2:p[6], fdjzs:p[25], dw:p[28], cs:p[23], + //@ts-ignore 方向盘 + fxp:p[27].split('_')[0]*1, + //累计脉冲 溜车脉冲 超声波左后 超声波右后 超声波右前 超声波左前 座椅 仪表盘 后视镜 倒车镜 光照 雨量 + ljmc:p[24], lcmc:0, csbzh:p[32], csbyh:p[30], csbyq:p[31], csbzq:p[29], zy:0, tbp:0, hsj:0, dcj:0, gx:0, yl:0, + //TODO 数据待替换 油压 闪灯 信号灯 + yy:0, sde:0, xhd:'',rmndg:0, wav:0 , mndg:'' + }, + gps:{ + //办卡类型 定位差分状态 + bklx:p[56], dwzt:p[83], + //@ts-ignore 角度差分状态 + jdzt:p[92].split('-')[0]*1, + //gps数据 + //gps时间 经度 纬度 航向角 俯仰角 海拔高 高度差 速度 + sj:time, jd:p[96], wd:p[95], hxj:p[90], fyj:p[91], hbg:p[85], gdc:p[86], sd:p[97], + //龄期 经度因子 纬度因子 定位搜星数 + age:p[87], jdyz:p[89], wdyz:p[88], dwsxs:p[84] || 0, + //@ts-ignore 角度搜星数 + jdsxs:p[92].split('-')[1]*1 || 0 + }, + gps2:data.gps, + vision:data.vision, + radar:data.radar, + extend:{} + } + return tempData +} + +export const plcStrToWXJson = async (plc:string) =>{ + const p = plc.split(',').map((val,key)=>{ + if(key !== 27 && key !== 92){ + //@ts-ignore + return val*1 + }else{ + return val + } + }); + const timeStr = p[93] + '' + p[94]; + const gps = { + //办卡类型 定位差分状态 + bklx:p[56], dwzt:p[83], + // 经度 纬度 航向角 俯仰角 海拔高 高度差 速度 + jd:p[96], wd:p[95], hxj:p[90], fyj:p[91], hbg:p[85], gdc:p[86], sd:p[97], + //龄期 经度因子 纬度因子 定位搜星数 + age:p[87], jdyz:p[89], wdyz:p[88], dwsxs:p[84], + } + const judgeSignal = [ + // 车门 安全带 熄火 发动机启动 左转向 右转向 前照灯近灯 前照灯远灯 + p[14], p[19], p[5], p[6], p[2], p[3], p[7], p[8], + // 注车制动 行车制动 离合器 副制动 喇叭 雨刷 危险报警灯 示廓灯 系统未涉及的传感器信号 + p[13], p[12], p[17], p[18], p[4], p[11], p[20], p[9], 0 + ] + const judgeAnotherSignal = [ + // 低三挡位 左侧单边桥1 左侧单边桥2 右侧单边桥1 右侧单边桥2 雾灯 + '000', '0', '0', '0', '0', p[10], + // 桩杆全无信号 左后绕车 右后绕车 右前绕车 左前绕车 + '000', '0', '0', '0', '0' + ] + const wuXiData = [ + // 卫星时间 精度 纬度 高度 方位角 俯仰角 速度角 速度 横滚 卫星定位状态 + '$KSXT', timeStr, gps.jd, gps.wd, gps.hbg, gps.hxj, gps.fyj, '' , gps.sd, '', gps.dwzt, gps.dwzt, + //前天线可用星数 后天线可用星数 东向坐标位置 北向位置坐标 天向位置坐标 东向速度 北向速度 天向速度 + '', '', '', '', '', '', '', '', + //@ts-ignore 评判信号1 评判信号2 发动机转速 + (judgeSignal.join('')*1).toString(16), (judgeAnotherSignal.join('')*1).toString(16) , p[25], + '0xFFFFFFF' + ] + const wuXiDataStr = wuXiData.join(',') + return wuXiDataStr +} + +export const senorToWXDataStr= async (tempData) => { + const {sensor,gps} = tempData; + const timeStr = await getTimeStr() + + const {mkg,aqd,dh1,dh2, zfxd, yfxd, jgd, ygd,ssc , jsc, lhq, fsc, lb, ygq,wd} = sensor + const judgeSignal = [ + //车门 安全带 熄火 发动机启动 左转向 右转向 前照灯近灯 前照灯远灯 + mkg, aqd, dh1, dh2, zfxd, yfxd, jgd, ygd, + // 注车制动 行车制动 离合器 副制动 喇叭 雨刷 危险报警灯 示廓灯 系统未涉及的传感器信号 + ssc , jsc, lhq, fsc, lb, ygq, 0, 0, 0 + ] + + const judgeAnotherSignal = [ + // 低三挡位 左侧单边桥1 左侧单边桥2 右侧单边桥1 右侧单边桥2 雾灯 + '000', '0', '0', '0', '0', '0',,'0', + // 桩杆全无信号 左后绕车 右后绕车 右前绕车 左前绕车 + '000', '0', '0', '0', '0', '0','0' + ] + //@ts-ignore + const str1 = (judgeSignal.join('')*1).toString(16); + //@ts-ignore + const str2 = (judgeAnotherSignal.join('')*1).toString(16); + + const wuXiData = [ + // 卫星时间 精度 纬度 高度 方位角 俯仰角 速度角 速度 横滚 卫星定位状态 + '$KSXT', timeStr, gps.jd, gps.wd, gps.hbg, gps.hxj, gps.fyj, '0' , gps.sd, '0', gps.dwzt, + //前天线可用星数 后天线可用星数 东向坐标位置 北向位置坐标 天向位置坐标 东向速度 北向速度 天向速度 + '0', '0', '0', '0', '0', '0', '0', '0','0', + //@ts-ignore 评判信号1 评判信号2 发动机转速 + // (judgeSignal.join('')*1).toString(16), (judgeAnotherSignal.join('')*1).toString(16) , sensor.fdjzs, + '0006', '0001' , sensor.fdjzs, + '0xFFFFFFF' + ] + return wuXiData.map(d => (d + '')).join(','); + // console.log('wuXiData',wuXiData.join(',')); +} + +export const getTimeStr = async () =>{ + const date = await systemTime.getDate() + const timeStr = ''; + const Y = date.getFullYear(); + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) ; + const D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()); + const h = (date.getHours() < 10 ? '0' + (date.getHours()) : date.getHours()); + const m = (date.getMinutes() < 10 ? '0' + (date.getMinutes()) : date.getMinutes()); + const s = (date.getSeconds() < 10 ? '0' + (date.getSeconds()) : date.getSeconds()); + const ss = (date.getMilliseconds() +'').slice(0,2); + return timeStr + Y + M +D +h +m +s +'.' + ss +} + +//蓝灯 +export function sendBlue(){ + const arrBlue = [0x55, 0xaa, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00]; + const arrBlueBuffer= Array2Byte(arrBlue).buffer + globalThis.lightLineUdp.send(arrBlueBuffer); +} + +//绿灯 +export function sendGreen(){ + const arrGreen = [0x55, 0xaa, 0x01, 0x00, 0x02, 0x00, 0x03, 0x01]; + const arrGreenBuffer= Array2Byte(arrGreen).buffer + globalThis.lightLineUdp.send(arrGreenBuffer); +} + +//红灯 +export function sendRed(){ + const arrRed= [0x55, 0xaa, 0x01, 0x01, 0x02, 0x00, 0x03, 0x00]; + const arrRedBuffer= Array2Byte(arrRed).buffer + globalThis.lightLineUdp.send(arrRedBuffer); +} + +export const defaultJudgeConfigObj = { +//结束考试方式 0-不合格继续 1-考试不合格报靠边停车 2-不合格不报靠边 3-训练不合格报靠边 4-自动退出 5-不合格自动退出 + 302:'5', + 332:'', +//是否能进行人工操作 0-不能人工评判 1-不能人工进项目 3-都不能 + 342:'', +//有项目未结束时可以靠边停车 0-否 1-是 + 343:'1', +//考试未结束且有扣分,是否可以退出 + 344:'0', +//直线行驶中是否可以进其它项目 0-否 1-是 + 348:'0', +//车上是否能点结束考试 0:否 1:是 + 353:'0', +//是否启动断电续考 0:否 1:是 + 369:'1', +//是否显示应考里程 + 375:'0', +//里程不够允许手工点靠边停车 + 387:'0', +//监管模式有扣分续考(0-否++1-是+把上次未考完的扣分带下来重新考试) + 432:'1' +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts new file mode 100644 index 00000000..d8fed5ac --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts @@ -0,0 +1,17 @@ + + +//考试回放开关 +export const judgeConfig = { + //本地目录开关 + isTrajectoryOpen: false, + //是否开启Udp + udpOpen:false, + // 本地模型地址 + modelPath: 'models/model_enc', + // 轨迹回放地址 + trajectoryPath: 'logs/2024_07_06/0000000000001_342323199501470011_测试学员1_2024_07_06_16_22_35/judge_exam_data.txt', + //TODO 济南临时特殊配置 + systemParamConfig:{ + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts new file mode 100644 index 00000000..931cb599 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts @@ -0,0 +1,48 @@ +import { + examJudgeMapSetParam, + examJudgeMapSetScaling +} from '../api/index' +import systemTime from '@ohos.systemDateTime'; + +import FileUtil from '../../../common/utils/File' +import FileModel from './fileModel' +import {testRealExam} from '../dataTest/index' + +const judgeTag = 'SURENJUN_JUDGE' + +export default class JudgeImg { + + private judgeUI + private modelPath:string + private fileModel:FileModel + private fileUtil:FileUtil + private plcData:any + + constructor(judgeUI) { + this.modelPath = 'models/model_enc' + this.judgeUI = judgeUI + this.fileUtil = new FileUtil(judgeUI.context) + this.fileModel = new FileModel(judgeUI.context) + this.init() + } + + async init(){ + const isJudgeInitBool = globalThis.isJudgeInitBool; + const {judgeUI} = this; + + //TODO 临时处理 + setTimeout(async ()=>{ + console.info(judgeTag,'1.进入评判入口') + await examJudgeMapSetParam(640, 480); //设置参数宽、高 + await examJudgeMapSetScaling(120); //设置缩放比例,一般默认填100(就是100%的意思) ,数字越大视野越大,数字越小视野越小,不能为0 + }) + + judgeUI.draw = true + + } + + //获取评判初始化数据 + getInitInfo = () =>{ + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts new file mode 100644 index 00000000..7925f759 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts @@ -0,0 +1,42 @@ +import Prompt from '@system.prompt' + +const TAG = 'SURENJUN_JUDGE' + +export default class JudgeTask{ + private queue = [] + private status:string + constructor() { + this.queue = [] + this.status = 'end' + } + + executeQueue = async ()=>{ + const {queue,executeQueue} = this + if(queue.length){ + for (const currentTask of queue) { + const {status} = this + try { + await currentTask(); + }catch (e){ + // console.info(TAG,'过程数据接口解析错误') + Prompt.showToast({ + message: '过程数据接口解析错误', + duration: 3000 + }); + } + this.queue.shift() + await executeQueue() + } + }else{ + this.status = 'end' + } + } + + addTask = async (fn) =>{ + this.queue.push(fn); + if(this.status == 'end' && this.queue.length === 1){ + await this.executeQueue(); + } + } + +} diff --git a/entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts b/entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts new file mode 100644 index 00000000..7be0b853 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts @@ -0,0 +1,150 @@ +import media from '@ohos.multimedia.media'; +import Prompt from '@system.prompt'; + +const TAG = 'VoiceAnnounce' + +export default class VoiceAnnounce{ + + //队列时候立马终止 + private isStopped:Boolean + private queue:String[] + private newQueue:String[] + private pendingQueue:String[] + private callback:Function; + constructor() { + this.isStopped = false; + this.queue = [] + } + + async playAudio(urls:string[],shit?:boolean,callback?:Function){ + const {isStopped,queue} = this; + this.callback = callback + if(shit){ + //队列清空,重新初始化 + this.isStopped = true; + this.newQueue = urls + } + if(queue.length){ + //队列续上 + this.queue = this.queue.concat(urls); + + }else{ + this.queue = urls + await this.executeQueue() + } + } + + async executeQueue(){ + const avPlayer = new AVPlayer(); + const go = async () => { + const {queue,callback,isStopped,newQueue} = this; + if(isStopped){ + //清空原来队列 + this.queue = newQueue + this.isStopped = false; + await go() + return + } + + await avPlayer.play(queue[0],callback); + this.queue.shift(); + console.info(TAG,JSON.stringify(this.queue),'堆栈弹出'); + if(this.queue.length){ + await go() + } + } + await go() + avPlayer.avPlayerStop(); + } + +} + + +class AVPlayer { + + public avPlayer:any = null; + + private voiceUrl: string[]; + private voiceStatus: 'completed' | 'playing' + private endCallback:Function + constructor() {} + + // 以下为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例 + async play(name,callback) { + this.endCallback = callback + const avPlayer = await media.createAVPlayer(); + this.avPlayer = avPlayer; + return new Promise(async (resolve,reject) => { + let url = '' + await this.setAVPlayerCallback(()=>{ + //@ts-ignore + resolve() + }); + try { + url = await globalThis.context.resourceManager.getRawFd(name); + this.avPlayer.fdSrc = url; + } catch (e) { + Prompt.showToast({ + message: `${name}语音文件不存在`, + duration: 4000 + }); + resolve(1) + } + }) + } + //音频播放队列 + public releasePlayer() { + this.avPlayer.release(); + } + + avPlayerStop() { + this.avPlayer && this.avPlayer.stop() + this.avPlayer && this.avPlayer.reset() + this.avPlayer && this.avPlayer.release() + } + // 注册avplayer回调函数 + setAVPlayerCallback(callBack) { + + this.avPlayer.on('error', (err) => { + this.avPlayer && this.avPlayer.stop() + this.avPlayer && this.avPlayer.reset() + this.avPlayer && this.avPlayer.release() + }) + + let num = 0; + // 状态机变化回调函数 + this.avPlayer.on('stateChange', async (state, reason) => { + const {endCallback} = this; + switch (state) { + case 'idle': // 成功调用reset接口后触发该状态机上报 + break; + case 'initialized': // avplayer 设置播放源后触发该状态上报 + this.avPlayer.prepare() + break; + case 'prepared': // prepare调用成功后上报该状态机 + this.avPlayer.play(); + this.voiceStatus = 'playing' + break; + case 'playing': // play成功调用后触发该状态机上报 + break; + case 'paused': // pause成功调用后触发该状态机上报 + break; + case 'completed': // 播放结束后触发该状态机上报 + this.voiceStatus = 'completed' + this.avPlayer.stop(); //调用播放结束接口 + if(endCallback){ + endCallback() + } + break; + case 'stopped': // stop接口成功调用后触发该状态机上报 + this.avPlayer.reset(); // 调用reset接口初始化avplayer状态 + callBack() + break; + case 'released': + break; + default: + break; + } + }) + } +} \ No newline at end of file -- 2.43.0.windows.1 From 514d3beb604bf51e4523487b38b73fdc7f758d76 Mon Sep 17 00:00:00 2001 From: lvyuankang <1344032923@qq.com> Date: Wed, 10 Jul 2024 14:31:55 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=B8=AD=E5=BF=83udp=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/build-profile.json5 | 6 ++++++ entry/src/main/ets/common/utils/GlobalUdp.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 index 1bf0a7d7..2160ea13 100644 --- a/entry/build-profile.json5 +++ b/entry/build-profile.json5 @@ -5,6 +5,11 @@ "path": "./src/main/cpp/CMakeLists.txt", "arguments": "", "cppFlags": "", + }, + "sourceOption": { + "workers": [ + './src/main/ets/workers/worker.ts' + ] } }, "targets": [ @@ -16,3 +21,4 @@ } ] } + diff --git a/entry/src/main/ets/common/utils/GlobalUdp.ts b/entry/src/main/ets/common/utils/GlobalUdp.ts index 123a1c86..9b22ebca 100644 --- a/entry/src/main/ets/common/utils/GlobalUdp.ts +++ b/entry/src/main/ets/common/utils/GlobalUdp.ts @@ -69,7 +69,7 @@ export async function getUDP2() { udpClient2.bindUdp() udpClient2.onError_Callback() - udpClient2.onMessage_1((val) => { + udpClient2.onMessage_2((val) => { if (val.id == '32') { globalThis.signNum = val.body[1] -- 2.43.0.windows.1 From 73360f518c2533e056b836f6eb49206bbfa1f2bd Mon Sep 17 00:00:00 2001 From: lvyuankang <1344032923@qq.com> Date: Thu, 11 Jul 2024 10:22:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B5=8E=E5=8D=97=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ets/pages/compontents/SignDisplayCom.ets | 8 +- entry/src/main/ets/pages/judgeSDK/judge.ts | 836 ++++++++++-------- .../ets/pages/judgeSDK/utils/file-photo.ts | 36 - .../main/ets/pages/judgeSDK/utils/fileLog.ts | 117 +++ .../ets/pages/judgeSDK/utils/fileModel.ts | 54 ++ .../ets/pages/judgeSDK/utils/filePhoto.ts | 71 ++ .../ets/pages/judgeSDK/utils/judgeCommon.ts | 397 +++++++++ .../ets/pages/judgeSDK/utils/judgeConfig.ts | 18 + .../ets/pages/judgeSDK/utils/judgeReal.ts | 48 + .../ets/pages/judgeSDK/utils/judgeTask.ts | 42 + .../judgeSDK/utils/voiceAnnouncements.ts | 165 ++++ 11 files changed, 1359 insertions(+), 433 deletions(-) delete mode 100644 entry/src/main/ets/pages/judgeSDK/utils/file-photo.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts create mode 100644 entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts diff --git a/entry/src/main/ets/pages/compontents/SignDisplayCom.ets b/entry/src/main/ets/pages/compontents/SignDisplayCom.ets index fb142cc6..eaf03065 100644 --- a/entry/src/main/ets/pages/compontents/SignDisplayCom.ets +++ b/entry/src/main/ets/pages/compontents/SignDisplayCom.ets @@ -1,5 +1,6 @@ import router from '@ohos.router'; -import FileLog from '../judgeSDK/utils/file-log'; +import UdpClient from '../../common/utils/UdpClient'; +import FileLog from '../judgeSDK/utils/fileLog'; import RealTime from '../compontents/judge/RealTime'; import { GPSData, SignalData } from '../../mock'; import { SignalDataType } from '../../model'; @@ -20,6 +21,7 @@ export default struct SignDisplayCom { @State @Watch('outClick') outFlag: boolean = false; @State url: string = '' private timer = null + private udpClient: UdpClient = null private FileLog: FileLog private vocObj = null; @@ -306,15 +308,13 @@ export default struct SignDisplayCom { if (showBack) { - this.ratio=1.2 - globalThis.udpClient&&globalThis.udpClient.onMessage_1((msg) => { + globalThis.udpClient.onMessage_1((msg) => { console.log('msgmsg', msg) if (msg) { getSignal(msg) } }) } else { - this.ratio=1 clearInterval(globalThis.signalTimer) globalThis.signalTimer = setInterval(() => { const msgStr = globalThis.msgStr diff --git a/entry/src/main/ets/pages/judgeSDK/judge.ts b/entry/src/main/ets/pages/judgeSDK/judge.ts index c16d8f3c..1af8f29a 100644 --- a/entry/src/main/ets/pages/judgeSDK/judge.ts +++ b/entry/src/main/ets/pages/judgeSDK/judge.ts @@ -2,19 +2,16 @@ import systemTime from '@ohos.systemDateTime'; import router from '@ohos.router'; import util from '@ohos.util'; import buffer from '@ohos.buffer'; - import { testKmItems, testMarkRules } from './dataTest/index'; import { EXAMDATA, SOUND } from './api/judgeSDK'; - -import VoiceAnnounce from './utils/voice-announcements'; -import FileModel from './utils/file-model'; -import FilePhoto from './utils/file-photo'; +import VoiceAnnounce from './utils/voiceAnnouncements'; +import FileModel from './utils/fileModel'; +import FilePhoto from './utils/filePhoto'; import FileUtil from '../../common/utils/File'; -import FileLog from '../judgeSDK/utils/file-log'; +import FileLog from './utils/fileLog'; -import JudgeTask from './utils/judge-task'; -import SimulateLights from './utils/simulate-lights'; -import { judgeConfig } from './utils/judge-config'; +import JudgeTask from './utils/judgeTask'; +import { judgeConfig } from './utils/judgeConfig'; import { uploadExamProgressData, writeObjectOut } from '../../api/judge'; import { @@ -36,35 +33,32 @@ import { plcStrToWXJson, promptWxCode, senorToWXDataStr -} from './utils/judge-common'; +} from './utils/judgeCommon'; import { examJudgeArtificialItem, examJudgeArtificialMark, examJudgeBeginExam, examJudgeEndExam, examJudgeInit, - examJudgeMapSetParam, - examJudgeMapSetScaling, + examJudgeSoundEnd, examJudgeRealExam, examJudgeSetLogCallback, examJudgeSetPerformCallback, examJudgeSetRealExamCallback } from './api/index'; import UsbService from '../../common/service/usbService'; + import Prompt from '@system.prompt'; const judgeTag = 'SURENJUN_JUDGE' export default class Judge { - - constructor(judgeUI) { this.serialIndex = 1; this.judgeUI = judgeUI //语音播放工具 this.avPlayer = new VoiceAnnounce(); - new SimulateLights(this.avPlayer) //模型工具 this.fileModel = new FileModel(judgeUI.context); //文件工具 @@ -104,7 +98,6 @@ export default class Judge { public async onJudgeFn(fn: Function) { await this.judging(fn) } - //开始评判 private async judging(callBack: Function) { const {judgeUI} = this; @@ -130,10 +123,10 @@ export default class Judge { await fileLog.setExamJudgeLogData(info); }) - console.info(judgeTag, '2.注册日志回调完成') + console.info(judgeTag, '2.注册日志回调完成',isTrajectoryOpen) let initInfo = isTrajectoryOpen ? JSON.parse(strArr[0]) : await this.getJudgeInitData(); - console.log('SURENJUN_JUDGE',isJudgeInitBool,isTrajectoryOpen,JSON.stringify(initInfo)) + //相关评判初始化只做一次 if (!isJudgeInitBool) { await fileLog.setExamJudgeData(initInfo) @@ -141,6 +134,7 @@ export default class Judge { globalThis.isJudgeInitBool = true console.info(judgeTag, '4.评判初始化完成') } else { + await fileLog.setExamJudgeData(initInfo) } globalThis.isJudge = true @@ -155,26 +149,21 @@ export default class Judge { console.info('评判实时数据', info) const performInfo = JSON.parse(info) this.performInfo = performInfo - this.judgeUI.jl = Math.ceil((performInfo.qjjl + performInfo.dcjl) / 100) + this.judgeUI.jl = Math.floor((performInfo.qjjl + performInfo.dcjl) / 100) }) + // 3.开始考试 let beginExamInfo = isTrajectoryOpen ? { ...JSON.parse(strArr[1]), replay: 1 } : await getJudgeBeginData() - console.log(judgeTag,'22222',JSON.stringify(beginExamInfo),strArr[1]) - await fileLog.setExamJudgeData(beginExamInfo) - console.log(judgeTag,'333333') - await examJudgeBeginExam(beginExamInfo); - console.log(judgeTag,'4444444') + await fileLog.setExamJudgeData(beginExamInfo) + await examJudgeBeginExam(beginExamInfo); console.info(judgeTag, '6.开始考试注册完成') avPlayer.playAudio(['voice/ksks.WAV']) - await examJudgeMapSetParam(640, 480); //设置参数宽、高 - await examJudgeMapSetScaling(120); //设置缩放比例,一般默认填100(就是100%的意思) ,数字越大视野越大,数字越小视野越小,不能为0 - this.judgeUI.draw = true // 处理轨迹plc信息 @@ -183,15 +172,308 @@ export default class Judge { return } - // 处理实时udp里的plc信号 globalThis.udpClient.onMessage_1(async (msg) => { handleUdp(msg) }) + } + // 获取评判初始化数据 + getJudgeInitData = async () => { + const {getModelData,getKm3JudgeInitConfig} = this + const carInfo = globalThis.carInfo; + const { examSubject,plateNo,carId } = carInfo; + const judgeUI = this.judgeUI + const {projectsObj,cdsbInfoObj,markRuleListObj,carType,carName,systemparmArr} = judgeUI + const examType = examSubject == 2 ? 'km2' : 'km3' + let allitems = []; + if (examSubject == 2) { + allitems = Reflect.ownKeys(cdsbInfoObj).map(cdsbKey => { + const cdsb = cdsbInfoObj[cdsbKey]; + const {xmdm,xmxh,modelKey} = cdsb + return { + xmdm, xmxh, model: getModelData(`${examType}/${modelKey}.txt`) + } + }) + } + const initInfo = { + kskm: examSubject * 1, + kchp: plateNo, + kchm: carId * 1, + kscx: carType, + cxcode: '1', + name: carName, + carmodel: getModelData(`${examType}/${carType}.txt`), + allitems, + iteminfo:[], + systemparm: systemparmArr, + mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules, + sysset: judgeUI.judgeConfig, + }; + let km3Config = {} + + if (examSubject == 3) { + km3Config = await getKm3JudgeInitConfig(); + } + // 获取科目三的评判配置 + console.info(judgeTag, '3.获取评判初始化数据完成') + return { + ...initInfo, + ...km3Config, + } + } + // 获取开始考试数据 + getJudgeBeginData = async () => { + const {code,name:examinerName} = globalThis.examinerInfo; + let currentParams: any = router.getParams(); + const {sczb,kfdm} = currentParams; + const {isExam} = this; + const judgeUI = this.judgeUI + const {projects,carType,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr} = judgeUI; + const beginInfo = { + kgid: '012', + kgxm: decodeURI(examinerName || ''), + exam: isExam ? 1 : 0, + //是否回放 + replay: 0, + //生成的轨迹文件 + track: '', + xm: judgeUI.name, + sex: 0, + kslsh: judgeUI.lsh, + sfzmhm: judgeUI.idCard, + ksyy: '', + kscx: carType, + kkcs: 1, + sfyk: 0, + ykkkcs: 1, + wayno: judgeUI.wayno * 1, + czlx: 0, + kskssj: await systemTime.getCurrentTime(), + ksxm: projects.map(project => { + return { + xmdm: project.projectCode * 1, + xmxh: '', + } + }), + //断点续考 + ddxk: isDdxk ? 1 : 0, + ddkssj: ddxkTime, + ykxm: isDdxk ? (ddxkKsxmArr?.map(projectCenterCode => (projectsCenterObj[projectCenterCode]?.projectCode) * 1)) : [], + kfxm: isDdxk ? (ddxkKfArr?.map(kf => { + const [xmdm, kfdm] = kf.split(',') + return { + xmdm: xmdm * 1, + kfdm + } + })) : [], + yklc: 0, + special: [], + //TODO 科目三参数临时写死 + sczb: (sczb === undefined || sczb == 0)?0:1, + sczbkf:kfdm, + dmndg: false, + nitem1: false, + nitem41: false, + mfxx: false, + mfxxn: false + } + console.info(judgeTag, '5.获取开始考试数据完成') + return beginInfo } + //处理评判过程回调 + handleRealExam = async (strData, callBack) => { + let examData: EXAMDATA = JSON.parse(strData); + const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,setRoadAndLane,judgeUI} = this; + const {carzt,xmks,kf,event,xmjs,ksjs,sound,mndg,lane} = examData + //获取项目结束、项目开始代码 + const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm + const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; + const isManualProjectIn = this.artSubject3ProjectsCodesArr.includes(xmdm); + const {examSubject} = this.judgeUI + switch (event) { + //项目开始 + case 1: + judgeUI.projectsObj[xmdm].type = '2'; + if(isManualProjectIn){ + //手动项目是否在进行中 + this.judgeUI.isManualProjectIn = true + } + if(xmdm == 41 && examSubject == 3){ + this.rmndg = 1 + } + this.judgeUI.currentXmdm = xmdm; + const xmmcStr = judgeUI.projectsObj[xmdm].name; + const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; + const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; + this.testKmItems[xmmcCode].status = 2; + this.xmmcStr = xmmcStr; + this.xmmcCode = xmmcCode; + this.xmmcSingleCode = xmmcSingleCode + this.xmdm = xmdm; + this.xmxh = xmxh; + this.judgeUI.isProjectIn = true; + this.judgeUI.isDeductedPopShow = true + break; + + //项目结束 + case 2: + judgeUI.projectsObj[xmdm].type = (xmjs.xmhg === 0 ? '4' : '3'); + this.judgeUI.isManualProjectIn = false + //统计必考项目数量 + this.xmmcStr = '无'; + this.xmmcCode = ''; + this.xmmcSingleCode = 0; + this.xmdm = ''; + this.judgeUI.isProjectIn = false; + this.judgeUI.isDeductedPopShow = false + this.judgeUI.currentXmdm = undefined; + break; + + //扣分 + case 3: + const thisKf = getKfStr(`${kf.xmdm}_${kf.kfdm}`) + //扣分信息 + this.kfArr.push({ + //扣分项目名称 + xmmcStr: getDqxmStr(kf.xmdm), + xmdm: kf.xmdm, + //扣分描述 + desc: thisKf.desc, + //扣分分数 + score: thisKf.score, + // 扣分无锡所代码 + markcatalog: thisKf.markcatalog, + markserial: thisKf.markserial, + kfxh: thisKf.kfxh + }) + this.judgeUI.totalScore += thisKf.score * 1; + break; + + //考车状态 + case 4: + this.carztStr = getCarStatus(carzt); + break; + + //考试结束 + case 5: + this.ksjs = ksjs; + break; + + //项目取消 + case 6: + break; + + //语音播放和提示 + case 7: + goJudgeVoice(sound) + break; + + //模拟灯光事件 + case 8: + setMndg(mndg) + break; + //车道和路段变化 + case 9: + this.judgeUI.lane = lane + break; + + default: + ;break; + + } + + const {xmmcStr,carztStr,kfArr} = this; + + await callBack({ + //项目名称 考车状态 扣分arr + xmmcStr, carztStr, kfArr + }); + + //语音播报 + this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs) + + //更新UI + if (event == 1 || event == 2 || event == 3) { + const copyProjectsObj = this.judgeUI.projectsObj; + judgeUI.projectsObj = deepClone(copyProjectsObj); + //科目三统计必考数量 + this.setCountItems() + } + } + // 更改考试状态 + goVoiceAnnounce = async (event, xmdm, kf, xmjs) => { + const {beginProject,pointsDedute,endProject,avPlayer,uploadProgressPhoto,judgeTask,handEndExam,judgeUI} = this; + const {projectsObj,judgeConfigObj,examSubject} = judgeUI; + const kfLen = kf.length + + //不报语音的项目列表 + const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',') + switch (event) { + + // 项目开始 + case 1: + const code = projectsObj[xmdm].projectCodeCenter; + const kmCode = getKmProjectVoice(code, 1) + if (!ignoreVoiceCodeArr.includes(code)) { + kmCode && avPlayer.playAudio([`voice/${kmCode}.mp3`]) + } + await judgeTask.addTask(async () => { + console.info(judgeTag, `项目开始-${xmdm}-${projectsObj[xmdm].name}`) + await beginProject(xmdm) + // console.info(judgeTag,'上传照片 start') + await uploadProgressPhoto(xmdm) + }) + break; + + // 项目结束 + case 2: + const endCode = projectsObj[xmdm].projectCodeCenter; + const endKmCode = getKmProjectVoice(endCode, 2) + if (!ignoreVoiceCodeArr.includes(endCode) && examSubject == 3) { + endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`]) + } + await judgeTask.addTask(async () => { + console.info(judgeTag, `项目结束-${xmdm}-${projectsObj[xmdm].name}`) + await endProject(xmdm); + //TODO 靠边停车结束 + if(xmdm === 11){ + + } + }) + break; + + // 扣分 + case 3: + //扣分时实时播报语音(0-否+1-是) + if(judgeConfigObj['418'] == '1'){ + avPlayer.playAudio([`voice/${kf[kfLen -1].markcatalog}.mp3`]) + } + await judgeTask.addTask(async () => { + console.info(judgeTag, `项目扣分-${kf[kfLen -1].markcatalog}-${kf[kfLen -1].desc}`) + await pointsDedute(kf[kfLen -1].xmdm, kf[kfLen -1]) + }) + break; + + // 考车状态 + case 4: + break + + // 考试结束 + case 5: + console.info(judgeTag,'考试结束') + clearInterval(globalThis.judgeTimer) + await judgeTask.addTask(async () => { + console.info(judgeTag, '考试结束 start') + await handEndExam() + }) + break + default: + break + } + } // 项目开始接口同步 beginProject = async (ksxm) => { const carInfo = globalThis.carInfo; @@ -332,32 +614,33 @@ export default class Judge { fileLog.setExamJudgeWuxiData(data) console.info(judgeTag, '上传照片 end') } - // 评判语音提示 goJudgeVoice = async (sound: SOUND) => { - const {avPlayer} = this; - const {xmdm,code} = sound; + const {avPlayer,fileLog} = this; + const {xmdm,code,type} = sound; //判断是不是模拟灯光语音 - const isLight = code.slice(0, 3) === '417'; - if (isLight) { + console.info(judgeTag,JSON.stringify(sound)) + if(type == 1){ console.info(judgeTag, '模拟灯光开始播放:' + code) } avPlayer.playAudio([`voice/${code}.mp3`], true, () => { - if (isLight) { + if (type == 1) { console.info(judgeTag, '播放结束:' + code) - setTimeout(() => { - this.wav = 1; + examJudgeSoundEnd({itemno:xmdm,code,type}) + fileLog.setExamJudgeData({ + method: 'examJudgeSoundEnd', + itemno: xmdm, + code, + type, }) } }) - - } - // 处理考试结束 public handEndExam = async (isManual?: Boolean) => { - const {isExam,judgeUI,endExam,handleSEP,avPlayer} = this; - const {judgeConfigObj,totalScore} = judgeUI + const {isExam,judgeUI,endExam,handleSEP,kfArr,avPlayer,judgeTask} = this; + const singlePlay = globalThis.singlePlay + const {judgeConfigObj,totalScore,} = judgeUI if (judgeConfigObj['344'] == 1) { Prompt.showToast({ @@ -367,43 +650,44 @@ export default class Judge { return } + //TODO 科目三考试合格 考官综合评判 + + //TODO 语音播放扣分项 + let score = 0; + if(kfArr.length){ + avPlayer.playAudio([`voice/kfdesc.mp3`]) + kfArr.forEach(kf => { + score += Math.abs(Number(kf.score)); + if(score <= 100){ + judgeTask.addTask(()=>{ + avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`]) + }) + } + }) + } await handleSEP(306); - avPlayer.playAudio(['voice/exam_waiting.mp3'], true) - this.isEnd = true - try { - const bytes = await this.getMessageHeartbeat(true); - const singlePlay = globalThis.singlePlay - singlePlay || globalThis.judgeUdp.send(bytes) - //结束评判函数 - await examJudgeEndExam(); - globalThis.isJudge = false - await endExam(isManual) - - } catch (e) { - setTimeout(() => { - router.back(); - }, 3000) - } - - } - - // 当前项目转换 - getDqxmStr = (type) => { - const projectsObj = this.judgeUI.projectsObj - return projectsObj[type]?.abbreviation || '通用评判' - } - - // 扣分项目转换 - getKfStr = (code) => { - const markRuleListObj = this.judgeUI.markRuleListObj; - const thisMark = markRuleListObj[code] - return { - desc: thisMark.markshow, - score: thisMark.markreal, - markcatalog: thisMark.markcatalog, - markserial: thisMark.markserial, - kfxh: thisMark.kfxh - } + judgeTask.addTask(()=>{ + avPlayer.playAudio(['voice/exam_waiting.mp3'],false,async ()=>{ + this.isEnd = true + try { + if(!singlePlay){ + const bytes = await this.getMessageHeartbeat(true); + globalThis.judgeUdp.send(bytes) + } + //结束评判函数 + await examJudgeEndExam(); + globalThis.isJudge = false + //TODO endExam函数逻辑待验证 + !singlePlay && await endExam(isManual) + router.back(); + } catch (e) { + // setTimeout(() => { + // // avPlayer.avPlayerStop(); + // router.back(); + // }, 3000) + } + }) + }) } // 考试结束 @@ -436,74 +720,48 @@ export default class Judge { promptWxCode('17C56', code) console.info(judgeTag, '考试结束 end') if (!isManual) { - if (totalScore < 80) { - judgeUI.loadingPopupVisible = true - if (kssycs == 1) { - avPlayer.playAudio(['voice/unqualified_one.wav'], true) - } else { - avPlayer.playAudio(['voice/unqualified_two.wav'], true) - } + judgeUI.loadingPopupVisible = true; + if (examSubject == 2 && totalScore < 80) { + avPlayer.playAudio([ + `voice/unqualified_${kssycs == 1?'one':'two'}.wav`, + ], true) } else { avPlayer.playAudio(['voice/qualified.mp3'], true) } + + if (examSubject == 3 && totalScore < 90) { + avPlayer.playAudio([ + `voice/${kssycs == 1?'exam_no_pass':'exam_no_pass_finish'}.mp3`, + ], true) + } else { + avPlayer.playAudio(['voice/exam_pass.mp3'], true) + } } console.info(judgeTag, `考试成绩:${totalScore}`) - fileLog.setExamJudgeWuxiData(data) + // fileLog.setExamJudgeWuxiData(data) await uploadProgressData(); setTimeout(() => { router.back(); }, 3000) } - - // 获取评判初始化数据 - getJudgeInitData = async () => { - const {getModelData,getKm3JudgeInitConfig} = this - const carInfo = globalThis.carInfo; - const { examSubject,plateNo,carId } = carInfo; - const {fileLog} = this - const judgeUI = this.judgeUI - const {projectsObj,cdsbInfoObj,markRuleListObj,carType,carName} = judgeUI - - const examType = examSubject == 2 ? 'km2' : 'km3' - - let allitems = []; - - if (examSubject == 2) { - allitems = Reflect.ownKeys(cdsbInfoObj).map(cdsbKey => { - const cdsb = cdsbInfoObj[cdsbKey]; - const {xmdm,xmxh,modelKey} = cdsb - return { - xmdm, xmxh, model: getModelData(`${examType}/${modelKey}.txt`) - } - }) - } - const initInfo = { - kskm: examSubject * 1, - kchp: plateNo, - kchm: carId * 1, - kscx: carType, - cxcode: '1', - name: carName, - carmodel: getModelData(`${examType}/${carType}.txt`), - allitems, - mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules, - sysset: judgeUI.judgeConfig, - }; - - let km3Config = {} - - if (examSubject) { - km3Config = await getKm3JudgeInitConfig(); - } - // 获取科目三的评判配置 - console.info(judgeTag, '3.获取评判初始化数据完成') + // 当前项目转换 + getDqxmStr = (type) => { + const projectsObj = this.judgeUI.projectsObj + return projectsObj[type]?.abbreviation || '通用评判' + } + // 扣分项目转换 + getKfStr = (code) => { + const markRuleListObj = this.judgeUI.markRuleListObj; + const thisMark = markRuleListObj[code] return { - ...initInfo, - ...km3Config, + desc: thisMark.markshow, + score: thisMark.markreal, + markcatalog: thisMark.markcatalog, + markserial: thisMark.markserial, + kfxh: thisMark.kfxh } } - // 消息心跳发送 getMessageHeartbeat = async (isEnd?: Boolean) => { const carInfo = globalThis.carInfo; @@ -603,66 +861,6 @@ export default class Judge { this.serialIndex += 1; return Array2Byte(tempArr) } - - // 获取开始考试数据 - getJudgeBeginData = async () => { - console.log('globalThis.carInfo.wayno',globalThis.carInfo.wayno) - const {code,name:examinerName} = globalThis.examinerInfo; - const {isExam,isTrajectoryOpen} = this; - const judgeUI = this.judgeUI - const {projects,carType,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr} = judgeUI; - const beginInfo = { - kgid: '012', - kgxm: decodeURI(examinerName || ''), - exam: isExam ? 1 : 0, - //是否回放 - replay: 0, - //生成的轨迹文件 - track: '', - xm: judgeUI.name, - sex: 0, - kslsh: judgeUI.lsh, - sfzmhm: judgeUI.idCard, - ksyy: '', - kscx: carType, - kkcs: 1, - sfyk: 0, - ykkkcs: 1, - wayno: Number(globalThis.carInfo.wayno)|| 0, - czlx: 0, - kskssj: await systemTime.getCurrentTime(), - ksxm: projects.map(project => { - return { - xmdm: project.projectCode * 1, - xmxh: '', - } - }), - //断点续考 - ddxk: isDdxk ? 1 : 0, - ddkssj: ddxkTime, - ykxm: isDdxk ? (ddxkKsxmArr?.map(projectCenterCode => (projectsCenterObj[projectCenterCode]?.projectCode) * 1)) : [], - kfxm: isDdxk ? (ddxkKfArr?.map(kf => { - const [xmdm, kfdm] = kf.split(',') - return { - xmdm: xmdm * 1, - kfdm - } - })) : [], - yklc: 0, - special: [], - //TODO 科目三参数临时写死 - sczb: 0, - sczbkf: [], - dmndg: false, - nitem1: false, - nitem41: false, - mfxx: false, - mfxxn: false - } - console.info(judgeTag, '5.获取开始考试数据完成') - return beginInfo - } - //获取场地序号 getSbxh = (ksxm, xmxh) => { const {judgeUI} = this; @@ -690,7 +888,6 @@ export default class Judge { const sbxh = currentCdsb.sbbm || '00000000' return sbxh } - // 中心所有项目转换 getTranslateProject = () => { // const {testKmItems} = this; @@ -713,13 +910,11 @@ export default class Judge { } return arr.map(numStr => parseInt(numStr, 2)); } - // 获取考试项目详情 getProjectInfo = (projectCode) => { const judgeUI = this.judgeUI; return judgeUI.projectsObj[projectCode] } - // 获取模型数据 getModelData = (modelName) => { const modelPath = this.modelPath @@ -740,19 +935,16 @@ export default class Judge { return photoBase64 } } - //人工进入项目 - public setJudgeItem = async (itemno) => { - const {fileLog} = this - await examJudgeArtificialItem(itemno * 1); - + //人工操作项目 + public setJudgeItem = async (itemno,type:1|2) => { + const {fileLog} = this; + await examJudgeArtificialItem(itemno * 1,type); await fileLog.setExamJudgeData({ method: 'examJudgeArtificialItem', itemno: itemno * 1, - type: 1 + type }) - - console.info(judgeTag, `人工评判进入项目-${itemno}`) - + console.info(judgeTag, `人工评判${type == 1?'进入':'取消'}项目-${itemno}`) } //人工扣分 public setJudgeMark = async (itemno, serial) => { @@ -818,11 +1010,10 @@ export default class Judge { //获取科目三的评判初始化配置 getKm3JudgeInitConfig = async () => { const {judgeUI,getModelData} = this; - const {carinfoArrr,mapPointArr,mapPointItemArr,systemparmArr} = judgeUI; + const {carinfoArrr,mapPointArr,mapPointItemArr} = judgeUI; return { carinfo: carinfoArrr, map_point: mapPointArr, - systemparm: systemparmArr, map_point_item: mapPointItemArr, //科目三暂时为空 iteminfo: [], @@ -833,7 +1024,7 @@ export default class Judge { // 处理udp plc信号 handleUdp = async (msg) => { console.info('plc信号', msg) - const {fileLog,getPlcData} = this + const {fileLog,getPlcData,usbService} = this const stachArr = msg.split(',') const {isEnd} = this; if (stachArr[0] != '#DN_GD' || isEnd) { @@ -842,6 +1033,11 @@ export default class Judge { const plcData = await getPlcData(msg); // 4.过程数据 await fileLog.setExamJudgeData(plcData) + //检测到有无锡所设备接入,需要发送特定的数据,供检测 + if (usbService.isWXUSBDevice) { + const str = await senorToWXDataStr(msg); + usbService.sendUSB(str) + } await examJudgeRealExam(plcData) const udpIndex = globalThis.udpIndex; if (udpIndex % 5 === 0) { @@ -866,88 +1062,16 @@ export default class Judge { avPlayer.playAudio(['voice/406001.mp3']) } break; - - } } - public plcStr: string - private judgeUI - // 更改考试状态 - goVoiceAnnounce = async (event, xmdm, kf, xmjs) => { - const {projectsObj,judgeConfigObj} = this.judgeUI; - - const {beginProject,pointsDedute,endProject,avPlayer,uploadProgressPhoto,judgeTask,handEndExam} = this; - const xmhg = xmjs.xmhg - const kfLen = kf.length - - //不报语音的项目列表 - const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',') - switch (event) { - - // 项目开始 - case 1: - const code = projectsObj[xmdm].projectCodeCenter; - const kmCode = getKmProjectVoice(code, 1) - if (!ignoreVoiceCodeArr.includes(code)) { - kmCode && avPlayer.playAudio([`voice/${kmCode}.mp3`]) - } - await judgeTask.addTask(async () => { - console.info(judgeTag, `项目开始-${xmdm}-${projectsObj[xmdm].name}`) - await beginProject(xmdm) - // console.info(judgeTag,'上传照片 start') - await uploadProgressPhoto(xmdm) - }) - break; - - // 项目结束 - case 2: - const endCode = projectsObj[xmdm].projectCodeCenter; - const endKmCode = getKmProjectVoice(endCode, 2) - if (!ignoreVoiceCodeArr.includes(endCode)) { - endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`]) - } - await judgeTask.addTask(async () => { - console.info(judgeTag, `项目结束-${xmdm}-${projectsObj[xmdm].name}`) - await endProject(xmdm) - }) - break; - - // 扣分 - case 3: - avPlayer.playAudio([`voice/${kf[kfLen -1].markcatalog}.mp3`]) - await judgeTask.addTask(async () => { - console.info(judgeTag, `项目扣分-${kf[kfLen -1].markcatalog}-${kf[kfLen -1].desc}`) - await pointsDedute(kf[kfLen -1].xmdm, kf[kfLen -1]) - }) - break; - - // 考车状态 - case 4: - break - - // 考试结束 - case 5: - clearInterval(globalThis.judgeTimer) - await judgeTask.addTask(async () => { - console.info(judgeTag, '考试结束 start') - await handEndExam() - }) - break - default: - break - } - } - // 获取plc数据 getPlcData = async (plc: string) => { - const {fileLog,mndgStr,rmndg,wav} = this; + const {fileLog,mndgStr,rmndg} = this; await fileLog.setPlcProgressData(plc) //plc字符串转化成评判初始化数据 const tempData = await plcStrToJson(plc); //模拟灯光回放时刻 tempData.sensor.rmndg = rmndg; - //模拟灯光单个灯光结束时刻 - tempData.sensor.wav = wav; //模拟灯灯光灯光项目 tempData.sensor.mndg = mndgStr; //plc字符串转化成无锡所过程数据 @@ -958,17 +1082,14 @@ export default class Judge { this.plcStr = plc; this.mndgStr = ''; this.rmndg = 0; - this.wav = 0; globalThis.msgStr = plc return tempData } // 处理轨迹plc信号 handleTrajectoryUdp = async (strArr) => { - const {fileLog} = this; - console.log('kkkkk') + const {fileLog,setJudgeItem,setJudgeMark,endExam} = this; let num = 2; - const {usbService} = this; const judgeTimer = setInterval(async () => { const msg = JSON.parse(strArr[num]); await fileLog.setExamJudgeData(msg) @@ -983,118 +1104,52 @@ export default class Judge { this.tempData = msg this.plcData = msg globalThis.msgStr = '' - const str = await senorToWXDataStr(msg); - //检测到有无锡所设备接入,需要发送特定的数据,供检测 - if (usbService.isWXUSBDevice) { - usbService.sendUSB(str) + if(msg.method === 'examJudgeArtificialItem'){ + setJudgeItem(msg.itemno,msg.type) + } + if(msg.method === 'examJudgeArtificialMark'){ + setJudgeItem(msg.itemno,msg.serial) } await examJudgeRealExam(msg) num++ - }, 200) + }, 100) globalThis.judgeTimer = judgeTimer; } - //处理评判过程回调 - handleRealExam = async (strData, callBack) => { - // console.log('过程数据:' + strData); - let examData: EXAMDATA = JSON.parse(strData); - const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,judgeUI} = this; - const {carzt,xmks,kf,event,xmjs,ksjs,sound,mndg} = examData - - //获取项目结束、项目开始代码 - const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm - const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; - - switch (event) { - //项目开始 - case 1: - judgeUI.projectsObj[xmdm].type = '2'; - const xmmcStr = judgeUI.projectsObj[xmdm].name; - const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; - const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; - this.testKmItems[xmmcCode].status = 2; - this.xmmcStr = xmmcStr; - this.xmmcCode = xmmcCode; - this.xmmcSingleCode = xmmcSingleCode - this.xmdm = xmdm; - this.xmxh = xmxh; - - break; - - //项目结束 - case 2: - judgeUI.projectsObj[xmdm].type = (xmjs.xmhg === 0 ? '4' : '3'); - this.xmmcStr = '无'; - this.xmmcCode = ''; - this.xmmcSingleCode = 0; - this.xmdm = ''; - break; - - //扣分 - case 3: - const thisKf = getKfStr(`${kf.xmdm}_${kf.kfdm}`) - //扣分信息 - this.kfArr.push({ - //扣分项目名称 - xmmcStr: getDqxmStr(kf.xmdm), - xmdm: kf.xmdm, - //扣分描述 - desc: thisKf.desc, - //扣分分数 - score: thisKf.score, - // 扣分无锡所代码 - markcatalog: thisKf.markcatalog, - markserial: thisKf.markserial, - kfxh: thisKf.kfxh - }) - this.judgeUI.totalScore += thisKf.score * 1; - break; - - //考车状态 - case 4: - this.carztStr = getCarStatus(carzt); - break; - - //考试结束 - case 5: - this.ksjs = ksjs; - break; - - //项目取消 - case 6: - break; - - //语音播放和提示 - case 7: - goJudgeVoice(sound) - break; - - //模拟灯光事件 - case 8: - setMndg(mndg) - break; - - default: - ;break; - - } - - const {xmmcStr,carztStr,kfArr} = this; - - await callBack({ - //项目名称 考车状态 扣分arr - xmmcStr, carztStr, kfArr - }); - - //语音播报 - this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs) - - //更新UI - if (event == 1 || event == 2 || event == 3) { - const copyProjectsObj = this.judgeUI.projectsObj; - judgeUI.projectsObj = deepClone(copyProjectsObj) + // 统计必考项目数量 + setCountItems = async () => { + const carInfo = globalThis.carInfo; + const { examSubject} = carInfo; + const {projectsObj} = this.judgeUI; + if(examSubject == 3){ + //必考项目数量 必考项目已考数量 + let projectNum = 0,endProjectsNum =0; + Reflect.ownKeys(projectsObj).forEach(projectKey=>{ + const {type,isRequired} = projectsObj[projectKey]; + if(isRequired){ + projectNum += 1; + if(type == 3 || type == 4){ + endProjectsNum += 1; + } + } + }) + //必考项目除靠边停车是否全部完成 + this.judgeUI.isRequiredProjectsEnd = (projectNum - endProjectsNum === 0) } } + // 模拟灯光 + setMndg = async (mndgStr: string) => { + this.mndgStr = mndgStr + } + + // 路段信息处理 + setRoadAndLane = async (lane)=>{ + const {road,num,count} = lane; + + } + + public plcStr: string + private judgeUI private fileLog private totalScore: number private folderPath: string @@ -1102,13 +1157,7 @@ export default class Judge { private avPlayer private carztStr: string private rmndg: 0 | 1 - private wav: 0 | 1 private mndgStr: string | undefined - // 模拟灯光 - setMndg = async (mndgStr: string) => { - this.mndgStr = mndgStr - this.rmndg = 1; - } private xmmcStr: string private xmmcCode: string private xmmcSingleCode: number @@ -1159,5 +1208,6 @@ export default class Judge { private isTrajectoryOpen: boolean; // 调代理接口是否断网了 private isJudgeDisConnect: boolean; + private artSubject3ProjectsCodesArr:number[] = [3, 9, 4, 10, 12, 11] } \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/file-photo.ts b/entry/src/main/ets/pages/judgeSDK/utils/file-photo.ts deleted file mode 100644 index 2cfbba54..00000000 --- a/entry/src/main/ets/pages/judgeSDK/utils/file-photo.ts +++ /dev/null @@ -1,36 +0,0 @@ -import mediaLibrary from '@ohos.multimedia.mediaLibrary' -import onvifclient from '@ohos.onvifclient'; -import fs from '@ohos.file.fs' -import util from '@ohos.util'; -import FileUtil from '../../../common/utils/File' - -interface Params{ - userName:string - pwd:string - ip:string - port:string - rlls:string -} - -export default class FilePhoto{ - - private params:Params - private context:any - private fileUtil:FileUtil - public mediaTest - - constructor(context) { - (async ()=>{ - const fileUtil = new FileUtil(context) - const strConfig = await fileUtil.readFile('/mnt/hmdfs/100/account/device_view/local/files/logs/config/config3.txt'); - const config = JSON.parse(strConfig) - const {userName,ip,pwd,port,rlls} = config - this.params = {userName,pwd,ip,port,rlls} - this.context = context - this.fileUtil = fileUtil - })() - } - - public async getPhoto(){ - } -} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts b/entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts new file mode 100644 index 00000000..8cbf69b2 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/fileLog.ts @@ -0,0 +1,117 @@ +import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl' +import promptAction from '@ohos.promptAction' +import fileAccess from '@ohos.file.fileAccess' +import common from '@ohos.app.ability.common' +import Want from '@ohos.app.ability.Want' +import fs from '@ohos.file.fs' +import FileUtil from '../../../common/utils/File' +import {getCurrentTime} from '../../../common/utils/tools' + +interface StuInfo{ + name:string + lsh:string + idCard:string +} + +const LOGTAG = 'LOGTAG' +export default class FileLog { + + //后续文件路径待替换 + private fileUtil: FileUtil + private stuInfo: StuInfo + public folderPath: string + + constructor(context) { + const fileUtil = new FileUtil(context) + this.fileUtil = fileUtil + } + + // 设置文件夹 + public initFileLogo = async (stuInfo:StuInfo) => { + const {fileUtil,setExamLineData} = this + const {name,lsh,idCard} = stuInfo; + this.stuInfo = stuInfo; + const time = await getCurrentTime() + const date = time.split(' ')[0].split('-').join('_') + const hourTime = time.split(' ')[1].split(':').join('_') + const folderPath = await fileUtil.initFolder(`/logs/${date}/${lsh}_${idCard}_${name}_${date}_${hourTime}`); + this.folderPath = folderPath; + } + + // 过程文件数据 + public setExamProgressData = async (str:Object) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/exam_progress_data.txt`,JSON.stringify(str)); + } + + // 无锡所接口数据 + public setExamJudgeWuxiData = async (str) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/wuxi_exam_data.txt`,str); + } + + // 无锡所过程数据 + public setExamJudgeWuxiProgressData = async (str)=>{ + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/wuxi_progress_data.txt`,str); + } + + // plc文件数据 + public setPlcProgressData = async (str:Object) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/plc_data.txt`,JSON.stringify(str)); + } + + // 过程评判json数据 + public setExamJudgeData = async (str:Object) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/judge_exam_data.txt`,JSON.stringify(str)); + } + + // 过程评判回调数据 + public setExamJudgeCallbackData = async (str:string) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/judge_progress_callback_data.txt`,str); + } + + // 过程评判日志调数据 + public setExamJudgeLogData = async (str:string) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/judge_log_data.txt`,str); + } + + // 无锡所轨迹数据 + public setExamLineData = async (plcStr) => { + const {fileUtil,folderPath} = this; + const plcData = plcStr.split(','); + const time = await getCurrentTime(); + + const lineData = [ + /*帧头*/ time, + /*卫星时间*/time, + /*经度*/ plcData[95], + /*纬度*/ plcData[95], + /*高度*/ plcData[86], + /*方位角*/ 0, + /*俯仰角*/ plcData[91], + /*速度角*/'', + /*速度*/ plcData[97], + /*横滚*/'', + /*卫星定位状态*/'', + /*卫星定向状态*/'', + /*前天线可用星数*/'', + /*后天线可用星数*/'', + /*东向位置坐标*/'', + /*北向位置坐标*/'', + /*天向位置坐标*/'', + /*东向速度*/'', + /*北向速度*/'', + /*评判信号1*/[plcData[14],plcData[19],plcData[5],'',plcData[2],plcData[3],plcData[7],plcData[8],plcData[13],plcData[12],plcData[17],'',plcData[4],plcData[11],plcData[20],plcData[9],0].join(','), + /*评判信号2*/['',plcData[28],'','',plcData[10],'','','','','','','','','','','','',''].join(','), + /*发动机转速*/ plcData[25], + /*结束符*/ time, + ]; + + await fileUtil.editFile(`${folderPath}/exam_wuxi_data.txt`,JSON.stringify(lineData)); + }; +} diff --git a/entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts b/entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts new file mode 100644 index 00000000..a935a7fd --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/fileModel.ts @@ -0,0 +1,54 @@ +import FileUtil from '../../../common/utils/File' +import zlib from '@ohos.zlib'; +export default class FileModel{ + + //后续文件路径待替换 + private fileUtil: FileUtil + public folderPath: string + + constructor(context){ + (async ()=>{ + const fileUtil = new FileUtil(context) + this.fileUtil = fileUtil + })() + + } + + // 设置文件夹 + public initFolder = async () => { + const {fileUtil} = this + await fileUtil.initFolder(`/models/model_enc`); + const folderPath = await fileUtil.initFolder(`/models`); + this.folderPath = folderPath; + } + + // 存储zip文件并解压 + public storingFiles = async (str) => { + const {fileUtil,folderPath} = this; + await fileUtil.editFile(`${folderPath}/model.zip`,str,'overWrite') + + let options = { + level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION, + memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT, + strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY + }; + + zlib.unzipFile( + `${folderPath}/model.zip`, + `${folderPath}`, + options).then((data) => { + console.log("unzipFile result:" + data); + }).catch((err)=>{ + console.log("catch((err)=>" + err); + }) + + } + + //获取文件内容 + public getModelContent = (folderPath,fileName) => { + const {fileUtil} = this; + const content = fileUtil.getFileContent(`${folderPath}/${fileName}`) + return content; + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts b/entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts new file mode 100644 index 00000000..58aac620 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/filePhoto.ts @@ -0,0 +1,71 @@ +import mediaLibrary from '@ohos.multimedia.mediaLibrary' +import onvifclient from '@ohos.onvifclient'; +import fs from '@ohos.file.fs' +import util from '@ohos.util'; +import FileUtil from '../../../common/utils/File' + +interface Params{ + userName:string + pwd:string + ip:string + port:string + rlls:string +} + +export default class FilePhoto{ + + private params:Params + private context:any + private fileUtil:FileUtil + public mediaTest + + constructor(context) { + (async ()=>{ + const fileUtil = new FileUtil(context) + const strConfig = await fileUtil.readFile('/mnt/hmdfs/100/account/device_view/local/files/logs/config/config3.txt'); + const config = JSON.parse(strConfig) + const {userName,ip,pwd,port,rlls} = config + this.params = {userName,pwd,ip,port,rlls} + this.context = context + this.fileUtil = fileUtil + })() + } + + public async getPhoto(){ + const {params,context,fileUtil} = this; + const {userName,pwd,ip,port,rlls} = params; + const mediaTest = mediaLibrary.getMediaLibrary(context); + let mediaType = mediaLibrary.MediaType.IMAGE; + let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_IMAGE; + const path = await mediaTest.getPublicDirectory(DIR_DOCUMENTS); + + return new Promise(async (resolve)=>{ + mediaTest.createAsset(mediaType, 'judge_face.jpg', path,(error,asset)=>{ + asset.open('rw', (error, fd) => { + if (fd > 0) { + const file_path = "/mnt/hmdfs/100/account/device_view/local/files/Pictures/judge_face.jpg" + const result3 = onvifclient.getVideoSnapshot(`rtsp://${userName}:${pwd}@${ip}:${port}/h264/ch${rlls}/main/av_stream`,file_path,fd); + fs.closeSync(fd); + asset.close(fd); + fs.lstat(file_path).then((stat) => { + console.info("get link status succeed, the size of file is" + stat.size); + let file = fs.openSync(file_path, fs.OpenMode.READ_WRITE); + const size=Number(stat.size)+100 + let buf = new ArrayBuffer(size); + let num = fs.readSync(file.fd, buf); + const that = new util.Base64(); + const array = new Uint8Array(buf); + const result = that.encodeToStringSync(array);//base64圖片 + fileUtil.deleteF(file_path,3) + resolve(result) + }).catch((err) => { + console.info("get link status failed with error message: " + err.message + ", error code: " + err.code); + }); + } else { + console.error('baoyihu getVideoSnapshot File Open failed with error: ' + error); + } + }); + }); + }) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts new file mode 100644 index 00000000..fafeaeca --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeCommon.ts @@ -0,0 +1,397 @@ +import {string2Bytes,Array2Byte,getCurrentTime} from '../../../common/utils/tools' +import {testMarkRules,testRealExam,testKmItems} from '../dataTest/index' + +import promptAction from '@ohos.promptAction' +import systemTime from '@ohos.systemDateTime'; + +//获取本地扣分项 +export const getTestMarkRules = () =>{ + testMarkRules.map((mark:any) => { + return { + itemno:mark.itemno*1, + markcatalog:mark.markcatalog, + markshow:mark.markshow, + markreal:mark.markreal*1, + markserial:mark.markserial, + kfxh:mark.kfxh + } + }) +} + +// 中心信号转换 +export const getTranslateSignals = (tempItems) => { + const len = Math.floor(tempItems.length / 8); + const arr = []; + for(let i = 0;i < len;i++){ + const temp = tempItems.slice( i*8 , (i+1)*8 ); + arr.push(temp.join('')); + } + const temp = arr.map(numStr => parseInt(numStr,2)) + return temp.map(item => string2Bytes(item , 8)[0]) +} + +// c++评判考车行驶状态转换 +export function getCarStatus(status: -1 | 0 | 1):string { + switch (status){ + case -1:return '后退' + case 0:return '停车' + case 1:return '前进' + default :return '' + } +} + +// 当前考车中心状态转换 +export function getCarStatusType(carzt){ + switch (carzt){ + case -1:return [1,0] + case 0: return [0,0] + case 1: return [0,1] + } +} + + +// 中心实时项目状态转换 +export function getCenterProjectStatus(status){ + switch (status){ + //不考 + case 0:return '00' + //未考 + case 1:return '01' + //已考 + case 2:return '10' + } +} + +//获取科目三开始项目、结束项目语音 + +export function getKmProjectVoice( + projectCode, + // 1:项目开始 2:项目结束 + type: 1 | 2 +) { + const carInfo = globalThis.carInfo; + const { examSubject } = carInfo; + + if(examSubject == 2){ + return projectCode + } + + switch (projectCode*1){ + //直线行驶 + case 40300: return type === 1 ? 403001 : 403002 + //变更车道 + case 40500: return type === 1 ? 405001 : 405002 + //超车 + case 41400 : return type === 1 ? 414001 : undefined + //直线行驶 + case 40700 : return type === 1 ? 407001 : undefined + //左转 + case 40800 : return type === 1 ? 408001 : undefined + //右转 + case 40900 : return type === 1 ? 409001 : undefined + //通过人行横道 + case 41000 : return type === 1? 410001:undefined + //通过学校 + case 41100 : return type === 1 ? 411001:undefined + //通过车站 + case 41200 : return type === 1 ? 412001 : undefined + //会车 + case 41300 : return type === 1 ? 413001: 413002 + //靠边停车 + case 40600 : return type === 1 ? 406001 : undefined + //掉头 + case 41500 : return type === 1 ? 415001:undefined + //超车 + case 40400 : return type === 1 ? 404001:undefined + + default :return undefined + } + +} + +// 上传监管数据code转换 +export function promptWxCode( + jkid:'17C52' | '17C54' |'17C55' | '17C53' | '17C56', + code:number +){ + let toast = ''; + const singlePlay = globalThis.singlePlay + if(singlePlay){ + return + } + switch (jkid){ + //项目开始 + case '17C52': + switch (code){ + case 0:toast = '存在作弊嫌疑,已被取消或暂停考试';break; + case -1:toast = '无考生身份比对信息';break; + case -2:toast = '考试项目与考试安排信息不符';break; + case -3:toast = '考试设备未备案';break; + case -4:toast = '考试设备与考试项目不符';break; + case -5:toast = '考试设备使用状态异常';break; + case -6:toast = '考生考试车型与考试设备使用准驾车型范围不符';break; + case -7:toast = '该考生存在作弊嫌疑,已被暂停/取消考试';break; + case -8:toast = '项目开始时间不能小于科目开始时间';break; + case -9:toast = '存在未结束的考试项目、不能开始新的项目考试!';break; + case -10:toast = '科目三考车号牌不能为空';break; + case -11:toast = '同一考车存在未结束考试,不能开始应用于新的考试';break; + case -12:toast = '未找到考场记录';break; + case -13:toast = '未找到考车信息';break; + case -14:toast = '随机抽取考生的考车与当前考车不一致';break; + default:toast = '';break; + } + break; + //过程照片 + case '17C54': + switch (code){ + case -1:toast = '无当前科目考试信息';break; + case -2:toast = '考生身份证明号码与考生预约信息不符';break; + case -3:toast = '考试项目不正确';break; + case -4:toast = '考试过程中拍摄照片数量少于3张!';break; + case -5:toast = '考试项目不符合要求';break; + case -6:toast = '存在未结束的考试项目!';break; + } + break; + //项目结束 + case '17C55': + switch (code){ + case -1:toast = '无当前考试项目开始信息';break; + case -2:toast = '考生身份证明号码与考生预约信息不符';break; + case -3:toast = '考试项目不正确';break; + case -4:toast = '考试设备序号不正确!';break; + case -5:toast = '考试项目结束时间写入错误';break; + case -6:toast = '考生未进行身份认证';break; + case -7:toast = '项目考试过程信息记录被非法篡改';break; + case -8:toast = '每个考试项目中必须至少抓拍一张照片';break; + case -12:toast = '未找到考场记录';break; + case -13:toast = '未找到考车信息';break; + case -15:toast = '考试过程信息必须由考车上传';break; + case -90:toast = '考试项目已经结束、无需重传';break; + case -91:toast = '实际道路考试,在完成科目考试时统一结束';break; + default:break; + } + break; + //扣分 + case '17C53': + switch (code){ + case 0:toast = '已存在同一时间的同一扣分记录';break + case -1:toast = '无当前考试项目开始信息';break; + case -2:toast = '扣分时间大于项目开始时间!';break; + case -3:toast = '考试项目与扣分项不符';break; + case -4:toast = '项目考试过程中,请传入当前考试项目代码';break; + case -5:toast = '考生未进行身份认证';break; + case -6:toast = '扣分时间写入错误';break; + case -7:toast = '项目考试过程信息记录被非法篡改';break; + case -12:toast = '未找到考场记录';break; + case -13:toast = '未找到考车信息';break; + case -15:toast = '考试过程信息必须由考车上传';break; + default:toast = '';break + } + break; + //考试结束 + case '17C56': + switch (code){ + case -1:toast = '无当前科目考试信息';break; + case -2:toast = '考生身份证明号码与考生预约信息不符';break; + case -3:toast = '考试结束时间不正确';break; + case -4:toast = '考试过程中拍摄照片数量少于3张!';break; + case -5:toast = '考试项目不符合要求';break; + case -6:toast = '存在未结束的考试项目!';break; + case -7:toast = '传输的考试成绩非空';break; + case -91:toast = '考试成绩计算不一致';break; + case -91:toast = '日间考试已结束等待进行夜间考试';break; + default: toast = '';break + } + break; + default :break; + } + promptAction.showToast({ + message: decodeURIComponent(toast), + duration: 4000 + }); +} + +// 获取plc数据 +export const plcStrToJson = async (plc:string) =>{ + + const p = plc.split(',').map((val,key)=>{ + if(key !== 27 && key !== 92){ + //@ts-ignore + return val*1 + }else{ + return val + } + }); + let data:any = testRealExam; + const time = await systemTime.getCurrentTime() + const tempData = { + sensor:{ + //安全带 车门门开关 手刹 脚刹 副刹 离合器 喇叭 示宽灯 近光灯 远光灯 + aqd:p[19], mkg:p[14], ssc:p[13], jsc:p[12], fsc:p[18], lhq:p[17], lb:p[4], skd:p[9], jgd:p[7], ygd:p[8], + //左方向灯 右方向灯 双跳灯 雾灯 雨刮器 点火1 点火2 发动机转速 档位 车速 + zfxd:p[2], yfxd:p[3], shtd:p[20],wd:p[10], ygq:p[11], dh1:p[5], dh2:p[6], fdjzs:p[25], dw:p[28], cs:p[23], + //@ts-ignore 方向盘 + fxp:p[27].split('_')[0]*1, + //累计脉冲 溜车脉冲 超声波左后 超声波右后 超声波右前 超声波左前 座椅 仪表盘 后视镜 倒车镜 光照 雨量 + ljmc:p[24], lcmc:0, csbzh:p[32], csbyh:p[30], csbyq:p[31], csbzq:p[29], zy:0, tbp:0, hsj:0, dcj:0, gx:0, yl:0, + //TODO 数据待替换 油压 闪灯 信号灯 + yy:0, sde:0, xhd:'',rmndg:0, wav:0 , mndg:'' + }, + gps:{ + //办卡类型 定位差分状态 + bklx:p[56], dwzt:p[83], + //@ts-ignore 角度差分状态 + jdzt:p[92].split('-')[0]*1, + //gps数据 + //gps时间 经度 纬度 航向角 俯仰角 海拔高 高度差 速度 + sj:time, jd:p[96], wd:p[95], hxj:p[90], fyj:p[91], hbg:p[85], gdc:p[86], sd:p[97], + //龄期 经度因子 纬度因子 定位搜星数 + age:p[87], jdyz:p[89], wdyz:p[88], dwsxs:p[84] || 0, + //@ts-ignore 角度搜星数 + jdsxs:p[92].split('-')[1]*1 || 0 + }, + gps2:data.gps, + vision:data.vision, + radar:data.radar, + extend:{} + } + return tempData +} + +export const plcStrToWXJson = async (plc:string) =>{ + const p = plc.split(',').map((val,key)=>{ + if(key !== 27 && key !== 92){ + //@ts-ignore + return val*1 + }else{ + return val + } + }); + const timeStr = p[93] + '' + p[94]; + const gps = { + //办卡类型 定位差分状态 + bklx:p[56], dwzt:p[83], + // 经度 纬度 航向角 俯仰角 海拔高 高度差 速度 + jd:p[96], wd:p[95], hxj:p[90], fyj:p[91], hbg:p[85], gdc:p[86], sd:p[97], + //龄期 经度因子 纬度因子 定位搜星数 + age:p[87], jdyz:p[89], wdyz:p[88], dwsxs:p[84], + } + const judgeSignal = [ + // 车门 安全带 熄火 发动机启动 左转向 右转向 前照灯近灯 前照灯远灯 + p[14], p[19], p[5], p[6], p[2], p[3], p[7], p[8], + // 注车制动 行车制动 离合器 副制动 喇叭 雨刷 危险报警灯 示廓灯 系统未涉及的传感器信号 + p[13], p[12], p[17], p[18], p[4], p[11], p[20], p[9], 0 + ] + const judgeAnotherSignal = [ + // 低三挡位 左侧单边桥1 左侧单边桥2 右侧单边桥1 右侧单边桥2 雾灯 + '000', '0', '0', '0', '0', p[10], + // 桩杆全无信号 左后绕车 右后绕车 右前绕车 左前绕车 + '000', '0', '0', '0', '0' + ] + const wuXiData = [ + // 卫星时间 精度 纬度 高度 方位角 俯仰角 速度角 速度 横滚 卫星定位状态 + '$KSXT', timeStr, gps.jd, gps.wd, gps.hbg, gps.hxj, gps.fyj, '' , gps.sd, '', gps.dwzt, gps.dwzt, + //前天线可用星数 后天线可用星数 东向坐标位置 北向位置坐标 天向位置坐标 东向速度 北向速度 天向速度 + '', '', '', '', '', '', '', '', + //@ts-ignore 评判信号1 评判信号2 发动机转速 + (judgeSignal.join('')*1).toString(16), (judgeAnotherSignal.join('')*1).toString(16) , p[25], + '0xFFFFFFF' + ] + const wuXiDataStr = wuXiData.join(',') + return wuXiDataStr +} + +export const senorToWXDataStr= async (tempData) => { + const {sensor,gps} = tempData; + const timeStr = await getTimeStr() + + const {mkg,aqd,dh1,dh2, zfxd, yfxd, jgd, ygd,ssc , jsc, lhq, fsc, lb, ygq,wd} = sensor + const judgeSignal = [ + //车门 安全带 熄火 发动机启动 左转向 右转向 前照灯近灯 前照灯远灯 + mkg, aqd, dh1, dh2, zfxd, yfxd, jgd, ygd, + // 注车制动 行车制动 离合器 副制动 喇叭 雨刷 危险报警灯 示廓灯 系统未涉及的传感器信号 + ssc , jsc, lhq, fsc, lb, ygq, 0, 0, 0 + ] + + const judgeAnotherSignal = [ + // 低三挡位 左侧单边桥1 左侧单边桥2 右侧单边桥1 右侧单边桥2 雾灯 + '000', '0', '0', '0', '0', '0',,'0', + // 桩杆全无信号 左后绕车 右后绕车 右前绕车 左前绕车 + '000', '0', '0', '0', '0', '0','0' + ] + //@ts-ignore + const str1 = (judgeSignal.join('')*1).toString(16); + //@ts-ignore + const str2 = (judgeAnotherSignal.join('')*1).toString(16); + + const wuXiData = [ + // 卫星时间 精度 纬度 高度 方位角 俯仰角 速度角 速度 横滚 卫星定位状态 + '$KSXT', timeStr, gps.jd, gps.wd, gps.hbg, gps.hxj, gps.fyj, '0' , gps.sd, '0', gps.dwzt, + //前天线可用星数 后天线可用星数 东向坐标位置 北向位置坐标 天向位置坐标 东向速度 北向速度 天向速度 + '0', '0', '0', '0', '0', '0', '0', '0','0', + //@ts-ignore 评判信号1 评判信号2 发动机转速 + // (judgeSignal.join('')*1).toString(16), (judgeAnotherSignal.join('')*1).toString(16) , sensor.fdjzs, + '0006', '0001' , sensor.fdjzs, + '0xFFFFFFF' + ] + return wuXiData.map(d => (d + '')).join(','); + // console.log('wuXiData',wuXiData.join(',')); +} + +export const getTimeStr = async () =>{ + const date = await systemTime.getDate() + const timeStr = ''; + const Y = date.getFullYear(); + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) ; + const D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()); + const h = (date.getHours() < 10 ? '0' + (date.getHours()) : date.getHours()); + const m = (date.getMinutes() < 10 ? '0' + (date.getMinutes()) : date.getMinutes()); + const s = (date.getSeconds() < 10 ? '0' + (date.getSeconds()) : date.getSeconds()); + const ss = (date.getMilliseconds() +'').slice(0,2); + return timeStr + Y + M +D +h +m +s +'.' + ss +} + +//蓝灯 +export function sendBlue(){ + const arrBlue = [0x55, 0xaa, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00]; + const arrBlueBuffer= Array2Byte(arrBlue).buffer + globalThis.lightLineUdp.send(arrBlueBuffer); +} + +//绿灯 +export function sendGreen(){ + const arrGreen = [0x55, 0xaa, 0x01, 0x00, 0x02, 0x00, 0x03, 0x01]; + const arrGreenBuffer= Array2Byte(arrGreen).buffer + globalThis.lightLineUdp.send(arrGreenBuffer); +} + +//红灯 +export function sendRed(){ + const arrRed= [0x55, 0xaa, 0x01, 0x01, 0x02, 0x00, 0x03, 0x00]; + const arrRedBuffer= Array2Byte(arrRed).buffer + globalThis.lightLineUdp.send(arrRedBuffer); +} + +export const defaultJudgeConfigObj = { +//结束考试方式 0-不合格继续 1-考试不合格报靠边停车 2-不合格不报靠边 3-训练不合格报靠边 4-自动退出 5-不合格自动退出 + 302:'5', + 332:'', +//是否能进行人工操作 0-不能人工评判 1-不能人工进项目 3-都不能 + 342:'', +//有项目未结束时可以靠边停车 0-否 1-是 + 343:'1', +//考试未结束且有扣分,是否可以退出 + 344:'0', +//直线行驶中是否可以进其它项目 0-否 1-是 + 348:'0', +//车上是否能点结束考试 0:否 1:是 + 353:'0', +//是否启动断电续考 0:否 1:是 + 369:'1', +//是否显示应考里程 + 375:'0', +//里程不够允许手工点靠边停车 + 387:'0', +//监管模式有扣分续考(0-否++1-是+把上次未考完的扣分带下来重新考试) + 432:'1' +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts new file mode 100644 index 00000000..fadb674f --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeConfig.ts @@ -0,0 +1,18 @@ + + +//考试回放开关 +export const judgeConfig = { + //本地目录开关 + isTrajectoryOpen: false, + //是否开启Udp + udpOpen:false, + // 本地模型地址 + modelPath: 'models/model_enc', + // 轨迹回放地址 + // trajectoryPath: 'logs/2024_07_08/0000000000001_342323199501470011_测试学员1_2024_07_08_14_59_51/judge_exam_data.txt', + trajectoryPath: 'logs/2024_07_08/0000000000001_342323199501470011_测试学员1_2024_07_09_14_49_36/judge_exam_data.txt', + //TODO 济南临时特殊配置 + systemParamConfig:{ + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts new file mode 100644 index 00000000..931cb599 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeReal.ts @@ -0,0 +1,48 @@ +import { + examJudgeMapSetParam, + examJudgeMapSetScaling +} from '../api/index' +import systemTime from '@ohos.systemDateTime'; + +import FileUtil from '../../../common/utils/File' +import FileModel from './fileModel' +import {testRealExam} from '../dataTest/index' + +const judgeTag = 'SURENJUN_JUDGE' + +export default class JudgeImg { + + private judgeUI + private modelPath:string + private fileModel:FileModel + private fileUtil:FileUtil + private plcData:any + + constructor(judgeUI) { + this.modelPath = 'models/model_enc' + this.judgeUI = judgeUI + this.fileUtil = new FileUtil(judgeUI.context) + this.fileModel = new FileModel(judgeUI.context) + this.init() + } + + async init(){ + const isJudgeInitBool = globalThis.isJudgeInitBool; + const {judgeUI} = this; + + //TODO 临时处理 + setTimeout(async ()=>{ + console.info(judgeTag,'1.进入评判入口') + await examJudgeMapSetParam(640, 480); //设置参数宽、高 + await examJudgeMapSetScaling(120); //设置缩放比例,一般默认填100(就是100%的意思) ,数字越大视野越大,数字越小视野越小,不能为0 + }) + + judgeUI.draw = true + + } + + //获取评判初始化数据 + getInitInfo = () =>{ + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts b/entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts new file mode 100644 index 00000000..7925f759 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/judgeTask.ts @@ -0,0 +1,42 @@ +import Prompt from '@system.prompt' + +const TAG = 'SURENJUN_JUDGE' + +export default class JudgeTask{ + private queue = [] + private status:string + constructor() { + this.queue = [] + this.status = 'end' + } + + executeQueue = async ()=>{ + const {queue,executeQueue} = this + if(queue.length){ + for (const currentTask of queue) { + const {status} = this + try { + await currentTask(); + }catch (e){ + // console.info(TAG,'过程数据接口解析错误') + Prompt.showToast({ + message: '过程数据接口解析错误', + duration: 3000 + }); + } + this.queue.shift() + await executeQueue() + } + }else{ + this.status = 'end' + } + } + + addTask = async (fn) =>{ + this.queue.push(fn); + if(this.status == 'end' && this.queue.length === 1){ + await this.executeQueue(); + } + } + +} diff --git a/entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts b/entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts new file mode 100644 index 00000000..b8ac1b65 --- /dev/null +++ b/entry/src/main/ets/pages/judgeSDK/utils/voiceAnnouncements.ts @@ -0,0 +1,165 @@ +import media from '@ohos.multimedia.media'; +import Prompt from '@system.prompt'; +import url from '@ohos.url'; + +const TAG = 'VoiceAnnounce' + +export default class VoiceAnnounce{ + + //队列时候立马终止 + private isStopped:Boolean + private queue:{ + url:string, + callback?:Function + }[] + private newQueue:{ + url:string, + callback?:Function + }[] + private pendingQueue:String[] + private callback:Function; + constructor() { + this.isStopped = false; + this.queue = [] + } + + async playAudio(urls:string[],shit?:boolean,callback?:Function){ + const {isStopped,queue} = this; + // this.callback = callback + const tempUrls = urls.map((url,index)=>{ + return { + url, + callback:(index === urls.length - 1)?callback:undefined + } + }); + + if(shit){ + //队列清空,重新初始化 + this.isStopped = true; + this.newQueue = tempUrls + } + if(queue.length){ + //队列续上 + this.queue = this.queue.concat(tempUrls) + + }else{ + this.queue = tempUrls + await this.executeQueue() + } + } + + async executeQueue(){ + const avPlayer = new AVPlayer(); + const go = async () => { + const {queue,isStopped,newQueue} = this; + if(isStopped){ + //清空原来队列 + this.queue = newQueue + this.isStopped = false; + await go() + return + } + + await avPlayer.play(queue[0].url,queue[0].callback); + this.queue.shift(); + console.info(TAG,JSON.stringify(this.queue),'堆栈弹出'); + if(this.queue.length){ + await go() + } + } + await go() + avPlayer.avPlayerStop(); + } + +} + + +class AVPlayer { + + public avPlayer:any = null; + + private voiceUrl: string[]; + private voiceStatus: 'completed' | 'playing' + private endCallback:Function + constructor() {} + + // 以下为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例 + async play(name,callback) { + this.endCallback = callback + const avPlayer = await media.createAVPlayer(); + this.avPlayer = avPlayer; + console.info('surenjun',callback) + return new Promise(async (resolve,reject) => { + let url = '' + await this.setAVPlayerCallback(()=>{ + //@ts-ignore + resolve() + }); + try { + url = await globalThis.context.resourceManager.getRawFd(name); + this.avPlayer.fdSrc = url; + } catch (e) { + Prompt.showToast({ + message: `${name}语音文件不存在`, + duration: 4000 + }); + resolve(1) + } + }) + } + //音频播放队列 + public releasePlayer() { + this.avPlayer.release(); + } + + avPlayerStop = ()=> { + this.avPlayer && this.avPlayer.stop() + this.avPlayer && this.avPlayer.reset() + this.avPlayer && this.avPlayer.release() + } + // 注册avplayer回调函数 + setAVPlayerCallback(callBack) { + + this.avPlayer.on('error', (err) => { + this.avPlayer && this.avPlayer.stop() + this.avPlayer && this.avPlayer.reset() + this.avPlayer && this.avPlayer.release() + }) + + let num = 0; + // 状态机变化回调函数 + this.avPlayer.on('stateChange', async (state, reason) => { + const {endCallback} = this; + switch (state) { + case 'idle': // 成功调用reset接口后触发该状态机上报 + break; + case 'initialized': // avplayer 设置播放源后触发该状态上报 + this.avPlayer.prepare() + break; + case 'prepared': // prepare调用成功后上报该状态机 + this.avPlayer.play(); + this.voiceStatus = 'playing' + break; + case 'playing': // play成功调用后触发该状态机上报 + break; + case 'paused': // pause成功调用后触发该状态机上报 + break; + case 'completed': // 播放结束后触发该状态机上报 + this.voiceStatus = 'completed' + this.avPlayer.stop(); //调用播放结束接口 + if(endCallback){ + endCallback() + } + break; + case 'stopped': // stop接口成功调用后触发该状态机上报 + this.avPlayer.reset(); // 调用reset接口初始化avplayer状态 + callBack() + break; + case 'released': + break; + default: + break; + } + }) + } +} \ No newline at end of file -- 2.43.0.windows.1