fix: TCP UDP中心优化带阿米

This commit is contained in:
wangzhongjie 2025-06-13 16:54:11 +08:00
parent 0f95021737
commit 46244ac980
5 changed files with 268 additions and 254 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

@ -139,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

@ -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() {
@ -41,11 +44,14 @@ class CenterUDPBusiness {
console.log("心跳")
// 组装消息,一秒发送一次
this.timer = setInterval(() => {
SetSerialNumber()
// 生成流水号
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])
@ -70,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'
@ -137,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

@ -1,83 +1,84 @@
// 处理worker线程的消息tcp拿差分改正数,udp给后置机
import worker, { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope } from '@ohos.worker';
import { WorkerTag } from '../config';
import { WorkerMessage } from '../model';
import { CenterCallBackMsgType, WorkerBackMessage, WorkerMessage } from '../model';
import { CenterUDPBusinessInstance } from '../utils/business/CenterUdpBusiness';
import { DifferentialSignal } from '../utils/business/DifferentialSignal';
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)
ObtainUdpBusinessInstance.init(result.config)
// 初始化中心UDP
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信号
// ObtainUdpBusinessInstance.onMsg((data: string) => {
// // TODO
// // 需要观察
// console.log(WorkerTag, "后置机消息", data)
// // 收到后置机消息传出去提供给业务,data应该是个string
// workerPort.postMessage(
// JSON.stringify({
// type: 'obtainUdpData',
// data: data
// } as WorkerBackMessage))
// })
// CenterUDPBusinessInstance.onMsg((data: CenterCallBackMsgType) => {
// // TODO
// // 需要观察
// console.log(WorkerTag, "中心消息", data)
// // 收到中心指令发送出去
// workerPort.postMessage(
// JSON.stringify({
// type: 'centerUdpData',
// data: data
// } as WorkerBackMessage)
// )
// })
// 后置机回执PLC和GPS
ObtainUdpBusinessInstance.onMsg((data: string) => {
// TODO
// 需要观察
console.log(WorkerTag, "后置机消息", data)
// 收到后置机消息传出去提供给业务,data应该是个string
workerPort.postMessage(
JSON.stringify({
type: 'obtainUdpData',
data: data
} as WorkerBackMessage))
})
// 中心UDP回执消息
CenterUDPBusinessInstance.onMsg((data: CenterCallBackMsgType) => {
// TODO
// 需要观察
console.log(WorkerTag, "中心消息", data)
// 收到中心指令发送出去
workerPort.postMessage(
JSON.stringify({
type: 'centerUdpData',
data: data
} as WorkerBackMessage)
)
})
}
/**
* 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}`)
}