Compare commits

...

3 Commits

Author SHA1 Message Date
wangzhongjie
46244ac980 fix: TCP UDP中心优化带阿米 2025-06-13 16:54:11 +08:00
wangzhongjie
0f95021737 fix: TCP UDP中心通 2025-06-13 13:23:41 +08:00
wangzhongjie
9e9b34c0b4 fix: 视频问题修复 2025-06-13 10:15:33 +08:00
9 changed files with 279 additions and 244 deletions

View File

@ -3,7 +3,7 @@ import { CarInfoType, CenterCallBackMsgType, EnvironmentConfigurationType, UDPPa
export interface WorkerMessage {
config: EnvironmentConfigurationType;
carInfo: CarInfoType;
udpParam?: UDPParamType;
centerUdpParam?: UDPParamType;
otherMessage: OtherMessageType;
}

View File

@ -78,13 +78,10 @@ struct Index {
async onPageShow(): Promise<void> {
console.log("首页 onPageShow")
await UseAuth(this.context)
DifferentialAndSignal.init()
DifferentialAndSignal.onMsg(() => {
console.log("外层接受")
})
this.avPlayer.playAudio(['welcome.wav'])
this.baseInfo = AppStorage.get<BaseInfoType>('baseInfo')!
this.initParams()
AppStorage.setOrCreate('singlePlay', false)
this.num = 0
AppStorage.setOrCreate('lsh', '1111111111111')
@ -181,12 +178,6 @@ struct Index {
console.log("test1111")
await GetDeviceInfo(this.context)
this.carInfo = await GetCarInfo()
// TODO
// CenterUDPBusinessInstance.onMsg((data: CenterCallBackMsgType) => {
// if (data.id == 32) {
// AppStorage.setOrCreate('signNum', data.body[1])
// }
// },)
this.carInfo = AppStorage.get<CarInfoType>('carInfo')!
this.deviceId = this.carInfo.carNo || ""
await SetCurrentTime()
@ -199,6 +190,11 @@ struct Index {
// TODO
// CenterUDPBusinessInstance.startHeartBeat()
CreateAlbum(this.fileHelper)
// 启动worker通道
DifferentialAndSignal.init()
DifferentialAndSignal.onMsg(() => {
console.log("外层接受")
})
}
build() {

View File

@ -53,6 +53,7 @@ export async function GetCarInfo(): Promise<CarInfoType> {
if (res.obtainCarExamInfoRsp && res.obtainCarExamInfoRsp.body) {
const carInfo: ObtainCarExamInfoRspBody = res?.obtainCarExamInfoRsp?.body!
carInfo.plateNo = decodeURIComponent(carInfo.plateNo)
console.log("Worker received message car", JSON.stringify(carInfo))
AppStorage.setOrCreate('carInfo', carInfo)
return carInfo
}
@ -138,25 +139,25 @@ async function obtainSerialNumber(data: string) {
}
//设置流水号
export async function SetSerialNumber() {
const data = AppStorage.get<string>("liushuiNo") || "";
const serialNumberTime = AppStorage.get<string>("liushuiDate");
obtainSerialNumber(data);
const date = dayTs().format('YYYY-MM-DD HH:mm:ss');
if (data && serialNumberTime) {
const diffDays = dayTs().diff(serialNumberTime, 'day');
if (diffDays === 0) {
AppStorage.setOrCreate<string>('liushuiDate', date);
AppStorage.setOrCreate<string>('liushuiNo', '0');
} else {
AppStorage.setOrCreate<string>('liushuiNo', (Number(data) + 1).toString());
}
} else {
AppStorage.setOrCreate('liushuiNo', '0');
AppStorage.setOrCreate('liushuiDate', date);
}
}
// export async function SetSerialNumber() {
// const data = AppStorage.get<string>("liushuiNo") || "";
// const serialNumberTime = AppStorage.get<string>("liushuiDate");
// obtainSerialNumber(data);
// const date = dayTs().format('YYYY-MM-DD HH:mm:ss');
//
// if (data && serialNumberTime) {
// const diffDays = dayTs().diff(serialNumberTime, 'day');
// if (diffDays === 0) {
// AppStorage.setOrCreate<string>('liushuiDate', date);
// AppStorage.setOrCreate<string>('liushuiNo', '0');
// } else {
// AppStorage.setOrCreate<string>('liushuiNo', (Number(data) + 1).toString());
// }
// } else {
// AppStorage.setOrCreate('liushuiNo', '0');
// AppStorage.setOrCreate('liushuiDate', date);
// }
// }
export function CreateAlbum(fileHelper: FileHelper) {
const date = dayTs().format("YYYY-MM-DD")

View File

@ -107,7 +107,7 @@ struct VideoConfigPage {
Video({
src: this.openFlag ?
`rtsp://${this.videoConfig.userName}:${this.videoConfig.pwd}@${this.videoConfig.ip}:${this.videoConfig.port}/h264/ch${Reflect.get(this.videoConfig,
'port')}/main/av_stream` : '',
item.td)}/main/av_stream` : '',
currentProgressRate: this.curRate,
controller: item.controller
})

View File

@ -0,0 +1,25 @@
// 流水号生成获取
class SerialNumber {
private serialNumber: string = "000000";
// 生成流水号(外部手动调用)
generate() {
let num = Number(this.serialNumber) + 1;
if (num > 999999) {
num = 0; // 超过 999999 时重置为 000000
}
this.serialNumber = num.toString().padStart(6, "0");
}
// 获取当前流水号
get() {
return this.serialNumber;
}
// 重置流水号(可选)
reset() {
this.serialNumber = "000000";
}
}
export const SerialNumberInstance = new SerialNumber();

View File

@ -139,6 +139,7 @@ export default class UdpClient {
private bindEvent() {
this.udp?.on("message", value => {
let result = this.dealMethod?.(value.message)
console.log(UDPTag, "中心返回消息", result)
this.messageEvents.forEach(cb => {
cb(result)
})

View File

@ -10,7 +10,7 @@ import { fillZero, string2Bytes } from '../../pages/judgeSDK/utils/Common';
import { NumberToByteArray } from '../Common';
import UdpClient from '../UdpUtils';
import { UDPTag } from '../../config';
import { SetSerialNumber } from '../../pages/Index/utils';
import { SerialNumberInstance } from '../SerialNumber';
// 中心UDP业务逻辑
class CenterUDPBusiness {
@ -20,8 +20,11 @@ class CenterUDPBusiness {
private headLength: number = 9
private sendId: number = 0
private carInfo: CarInfoType = {}
// 指令
private signNum: number = -1
// 状态
private statue: string = ""
// 学员流水号
private lsh: string = ""
constructor() {
@ -38,21 +41,21 @@ class CenterUDPBusiness {
}
startHeartBeat() {
console.log("心跳")
// 组装消息,一秒发送一次
this.timer = setInterval(() => {
SetSerialNumber()
// const signNum = AppStorage.get<number>('signNum')
// const statue = AppStorage.get<string>('statue')
// const lsh = AppStorage.get<string>('lsh')
// 生成流水号
SerialNumberInstance.generate()
// SetSerialNumber()
const arr = [this.signNum || 0, this.statue || 1]
let tmpList: number[] = [];
tmpList.push(NumberToByteArray(Number(arr[0]), 1 * 8)[0])
tmpList.push(NumberToByteArray(Number(arr[1]), 1 * 8)[0])
// 学员流水号
const str = this.lsh || '0000000000000'
for (let i = 0; i < str.length; i++) {
tmpList.push(NumberToByteArray(str.charCodeAt(i), 1 * 8)[0])
}
// const carInfo = AppStorage.get<CarInfoType>('carInfo')!
const data: UDPParamType = {
id: 31,
list: tmpList,
@ -60,6 +63,7 @@ class CenterUDPBusiness {
placeId: this.carInfo.examinationRoomId!
}
const param = this.setWholeMsg(data)
console.log("查看")
this.udp.sendMsg(param);
}, 1000);
}
@ -72,12 +76,15 @@ class CenterUDPBusiness {
this.udp.offMsg(cb)
}
changeKeyValue(value: OtherMessageType) {
value.signNum && (this.signNum = value.signNum)
value.lsh && (this.lsh = value.lsh)
value.statue && (this.statue = value.statue)
}
// 初始化
async init(config: EnvironmentConfigurationType, carInfo: CarInfoType, otherMessage: OtherMessageType) {
try {
// let result: EnvironmentConfigurationType =
// AppStorage.get<EnvironmentConfigurationType>("EnvironmentConfiguration")!
// const carInfo: CarInfoType = AppStorage.get<CarInfoType>('carInfo')!
this.signNum = otherMessage.signNum || 0
this.statue = otherMessage.statue || '1'
this.lsh = otherMessage.lsh || '0000000000000'
@ -139,8 +146,10 @@ class CenterUDPBusiness {
}
private setMsgHead(params: UDPParamType) {
// 自增流水号
const lshNo = SerialNumberInstance.get()
let a = string2Bytes(Number(`${params.id}${fillZero(params.placeId, 3)}`), 2 * 8);
let b = string2Bytes(Number(`${fillZero(params.carNo, 4)}${AppStorage.get('lshNo')}`), 4 * 8);
let b = string2Bytes(Number(`${fillZero(params.carNo, 4)}${lshNo}`), 4 * 8);
let c = string2Bytes(params.list.length, 2 * 8);
let result: number[] = []
a?.forEach(item => result.push(item))

View File

@ -1,13 +1,14 @@
import { CarInfoType, EnvironmentConfigurationType, Gps, Sensor, UDPParamType } from '../../model'
import { CarInfoType, EnvironmentConfigurationType, Gps, Sensor, UDPParamType } from '../../model';
import { testKm2Items, testKm3Items } from '../../pages/judgeSDK/dataTest';
import { fillZero, } from '../../pages/judgeSDK/utils/Common';
import { JudgeConfig } from "../../config";
import { JudgeConfig } from '../../config';
import { FillZero, StringToASCII } from '../Common';
import UdpClient from '../UdpUtils'
import UdpClient from '../UdpUtils';
import { CenterUDPBusinessInstance } from './CenterUdpBusiness';
import { ObtainUdpBusinessInstance } from './ObtainUdpBusiness';
import systemTime from '@ohos.systemDateTime';
import { examCalcGpsDistance } from '../../pages/judgeSDK/api';
import { SerialNumberInstance } from '../SerialNumber';
interface PLCDataType {
sensor: Sensor,
@ -48,9 +49,9 @@ function string2Bytes(num: number | string, len: number) {
class JudgeUdpBusiness {
private static instance: JudgeUdpBusiness
public udpIndex = 0;
private udp: UdpClient = new UdpClient()
private currentUdpIndex = 0;
public udpIndex = 0;
constructor() {
if (!JudgeUdpBusiness.instance) {
@ -59,181 +60,6 @@ class JudgeUdpBusiness {
return JudgeUdpBusiness.instance
}
private setWholeMsg(params: UDPParamType) {
let head: Array<number> = this.setMsgHead(params);
let headJudge = this.setMessageExclusive(head);
let bodyJudge = this.setMessageExclusive(params.list);
let end = [13, 10];
const arr: Array<number> = [...head, ...headJudge, ...params.list, ...bodyJudge, ...end]
return this.array2Byte(arr).buffer
}
private array2Byte(array: Array<number>) {
const buf = new ArrayBuffer(array.length);
const view = new Uint8Array(buf);
for (let i = 0; i != array.length; ++i) {
view[i] = array[i] & 0xFF;
}
return view;
}
private setMsgHead(params: UDPParamType) {
let a = string2Bytes(Number(`${params.id}${fillZero(params.placeId, 3)}`), 2 * 8);
let b = string2Bytes(Number(`${fillZero(params.carNo, 4)}${AppStorage.get('lshNo')}`), 4 * 8);
let c = string2Bytes(params.list.length, 2 * 8);
let result: number[] = []
a?.forEach(item => result.push(item))
b?.forEach(item => result.push(item))
c?.forEach(item => result.push(item))
return result;
}
private setMessageExclusive(tmpList: Array<number>) {
let result: number = tmpList[0];
for (let i = 1; i < tmpList.length; i++) {
result = result ^ tmpList[i]
}
return [result];
}
private convertGpsCoord2(num: number) {
const tempNum = Math.floor(num);
const du = Math.floor(tempNum / 100);
const fen = tempNum % 100 + num - tempNum;
return du + fen / 60
}
// 中心plc实时信号转换成字节
private getTranslateSignals(tempItems: number[]) {
const len = Math.floor(tempItems.length / 8);
const arr: string[] = [];
for (let i = 0; i < len; i++) {
arr.push(tempItems.slice(i * 8, (i + 1) * 8).join(''));
}
return arr.map(numStr => parseInt(numStr, 2)).map(item => string2Bytes(item, 8)[0])
}
// 中心所有项目转换
private getTranslateProject(): string[] {
const examSubject = AppStorage.get<string>("examSubject");
const tempItems: ProjectItemType[] =
(examSubject === '2' ? testKm2Items : testKm3Items).map((code: ProjectDataType) => {
let data: ProjectItemType = {
code,
status: '0'
}
return data
})
const arr: string[] = [];
for (let i = 0; i <= 4; i++) {
const temp = tempItems.slice(i * 4, (i + 1) * 4);
let tempArr = temp.map(item => item.status)
if (i === 4) {
tempArr = examSubject === '2'
//bit36-bit39保留
? tempArr.concat(['00', '00'])
//bit30-bit39保留
: tempArr.concat(['00', '00', '00'])
}
arr.push(tempArr.join(''));
}
return arr
}
// plc数据转换成对象
private async getPlcData(plc: string): Promise<PLCDataType> {
const time = await systemTime.getCurrentTime()
let origin = plc.split(",")
let p = origin.map(item => Number(item))
let sensor: 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],
fxp: Number(origin[27].split('_')[0]),
//累计脉冲 溜车脉冲 超声波左后 超声波右后 超声波右前 超声波左前 座椅 仪表盘 后视镜 倒车镜 光照 雨量
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,
yy: 0,
sde: 0,
xhd: '',
rmndg: 0,
wav: 0,
mndg: ''
}
let gps: Gps = {
bklx: p[56],
dwzt: p[83],
jdzt: Number(origin[92].split('-')[0]),
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],
jdsxs: Number(origin[92].split('-')[1])
}
return {
sensor,
gps,
}
}
private getDwStatusType(dw: number) {
switch (dw) {
case 0:
return [0, 0, 0, 0]
case 1:
return [0, 0, 0, 1]
case 2:
return [0, 0, 1, 0]
case 3:
return [0, 0, 1, 1]
case 4:
return [0, 1, 0, 0]
case 5:
return [0, 1, 0, 1]
case 9:
return [1, 0, 0, 1]
default:
return [0, 0, 0, 0]
}
}
async getMessageHeartbeat(msg: string): Promise<number[]> {
const carInfo: CarInfoType = AppStorage.get<CarInfoType>('carInfo')!
let gpsDigit = JudgeConfig.fourInOneScreen.gpsDigit
@ -412,6 +238,182 @@ class JudgeUdpBusiness {
}
})
}
private setWholeMsg(params: UDPParamType) {
let head: Array<number> = this.setMsgHead(params);
let headJudge = this.setMessageExclusive(head);
let bodyJudge = this.setMessageExclusive(params.list);
let end = [13, 10];
const arr: Array<number> = [...head, ...headJudge, ...params.list, ...bodyJudge, ...end]
return this.array2Byte(arr).buffer
}
private array2Byte(array: Array<number>) {
const buf = new ArrayBuffer(array.length);
const view = new Uint8Array(buf);
for (let i = 0; i != array.length; ++i) {
view[i] = array[i] & 0xFF;
}
return view;
}
private setMsgHead(params: UDPParamType) {
const lshNo = SerialNumberInstance.get()
let a = string2Bytes(Number(`${params.id}${fillZero(params.placeId, 3)}`), 2 * 8);
let b = string2Bytes(Number(`${fillZero(params.carNo, 4)}${lshNo}`), 4 * 8);
let c = string2Bytes(params.list.length, 2 * 8);
let result: number[] = []
a?.forEach(item => result.push(item))
b?.forEach(item => result.push(item))
c?.forEach(item => result.push(item))
return result;
}
private setMessageExclusive(tmpList: Array<number>) {
let result: number = tmpList[0];
for (let i = 1; i < tmpList.length; i++) {
result = result ^ tmpList[i]
}
return [result];
}
private convertGpsCoord2(num: number) {
const tempNum = Math.floor(num);
const du = Math.floor(tempNum / 100);
const fen = tempNum % 100 + num - tempNum;
return du + fen / 60
}
// 中心plc实时信号转换成字节
private getTranslateSignals(tempItems: number[]) {
const len = Math.floor(tempItems.length / 8);
const arr: string[] = [];
for (let i = 0; i < len; i++) {
arr.push(tempItems.slice(i * 8, (i + 1) * 8).join(''));
}
return arr.map(numStr => parseInt(numStr, 2)).map(item => string2Bytes(item, 8)[0])
}
// 中心所有项目转换
private getTranslateProject(): string[] {
const examSubject = AppStorage.get<string>("examSubject");
const tempItems: ProjectItemType[] =
(examSubject === '2' ? testKm2Items : testKm3Items).map((code: ProjectDataType) => {
let data: ProjectItemType = {
code,
status: '0'
}
return data
})
const arr: string[] = [];
for (let i = 0; i <= 4; i++) {
const temp = tempItems.slice(i * 4, (i + 1) * 4);
let tempArr = temp.map(item => item.status)
if (i === 4) {
tempArr = examSubject === '2'
//bit36-bit39保留
? tempArr.concat(['00', '00'])
//bit30-bit39保留
: tempArr.concat(['00', '00', '00'])
}
arr.push(tempArr.join(''));
}
return arr
}
// plc数据转换成对象
private async getPlcData(plc: string): Promise<PLCDataType> {
const time = await systemTime.getCurrentTime()
let origin = plc.split(",")
let p = origin.map(item => Number(item))
let sensor: 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],
fxp: Number(origin[27].split('_')[0]),
//累计脉冲 溜车脉冲 超声波左后 超声波右后 超声波右前 超声波左前 座椅 仪表盘 后视镜 倒车镜 光照 雨量
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,
yy: 0,
sde: 0,
xhd: '',
rmndg: 0,
wav: 0,
mndg: ''
}
let gps: Gps = {
bklx: p[56],
dwzt: p[83],
jdzt: Number(origin[92].split('-')[0]),
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],
jdsxs: Number(origin[92].split('-')[1])
}
return {
sensor,
gps,
}
}
private getDwStatusType(dw: number) {
switch (dw) {
case 0:
return [0, 0, 0, 0]
case 1:
return [0, 0, 0, 1]
case 2:
return [0, 0, 1, 0]
case 3:
return [0, 0, 1, 1]
case 4:
return [0, 1, 0, 0]
case 5:
return [0, 1, 0, 1]
case 9:
return [1, 0, 0, 1]
default:
return [0, 0, 0, 0]
}
}
}
export const JudgeUdpBusinessInstance = new JudgeUdpBusiness()

View File

@ -8,17 +8,28 @@ import { ObtainUdpBusinessInstance } from '../utils/business/ObtainUdpBusiness';
const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
/**
* Defines the event handler to be called when the worker thread receives a message sent by the host thread.
* The event handler is executed in the worker thread.
*
* @param e message data
*/
workerPort.onmessage = (e: MessageEvents) => {
console.log(WorkerTag, `Worker received message: ${e.data}`);
const result: WorkerMessage = JSON.parse(e.data);
// 初始化TCP
initFn(result)
// TODO 内部已经实现,外部未实现
// 如果外部有这个值就去更新中心这个值
if (result.otherMessage) {
CenterUDPBusinessInstance.changeKeyValue(result.otherMessage)
}
// 如果外部有这个消息进来就开始给中心发送,暂时看不需要
// if (result.centerUdpParam) {
// CenterUDPBusinessInstance.sendData(result.centerUdpParam);
// }
getDataFn()
}
// 初始化函数
function initFn(result: WorkerMessage) {
// 初始化差分校正TCP
DifferentialSignal.init(result.config);
// 定时发送TCP消息
DifferentialSignal.sendData()
// 初始化后置机UDP
ObtainUdpBusinessInstance.init(result.config)
@ -26,17 +37,16 @@ workerPort.onmessage = (e: MessageEvents) => {
CenterUDPBusinessInstance.init(result.config, result.carInfo, result.otherMessage)
// 中心心跳
CenterUDPBusinessInstance.startHeartBeat()
// 如果外部有这个消息进来就开始给中心发送
if (result.udpParam) {
CenterUDPBusinessInstance.sendData(result.udpParam);
}
}
function getDataFn() {
// 获取TCP差分改正数信号
DifferentialSignal.getData((data: ArrayBuffer) => {
console.log(WorkerTag, "Received differential signal data:", data.byteLength, "bytes")
// TCP拿到差分改正数发给后置机
ObtainUdpBusinessInstance.sendData(data)
})
// 监听PLC和GPS信号
// 后置机回执PLC和GPS
ObtainUdpBusinessInstance.onMsg((data: string) => {
// TODO
// 需要观察
@ -48,6 +58,7 @@ workerPort.onmessage = (e: MessageEvents) => {
data: data
} as WorkerBackMessage))
})
// 中心UDP回执消息
CenterUDPBusinessInstance.onMsg((data: CenterCallBackMsgType) => {
// TODO
// 需要观察
@ -62,22 +73,12 @@ workerPort.onmessage = (e: MessageEvents) => {
})
}
/**
* Defines the event handler to be called when the worker receives a message that cannot be deserialized.
* The event handler is executed in the worker thread.
*
* @param e message data
*/
workerPort.onmessageerror = (e: MessageEvents) => {
console.log(WorkerTag, `Worker received message error: ${e.data}`);
}
/**
* Defines the event handler to be called when an exception occurs during worker execution.
* The event handler is executed in the worker thread.
*
* @param e error message
*/
workerPort.onerror = (e: ErrorEvent) => {
console.log(WorkerTag, `Worker error: ${e.message}, filename: ${e.filename}, lineno: ${e.lineno}, colno: ${e.colno}`)
}