feat:后置机类型配置修改
This commit is contained in:
parent
5c3846f303
commit
5ea306d700
Binary file not shown.
78
entry/src/main/ets/common/rearEndUnitsTool/index.ts
Normal file
78
entry/src/main/ets/common/rearEndUnitsTool/index.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import FileUtil from '../utils/File';
|
||||||
|
import { GlobalConfig } from '../../config';
|
||||||
|
import common from '@ohos.app.ability.common';
|
||||||
|
import UdpByOne from './tool/UdpByOne';
|
||||||
|
|
||||||
|
export default class TerClient {
|
||||||
|
|
||||||
|
//一型机 二型机 三型机 一体机
|
||||||
|
public terType: 0 | 1 | 2 | 3 = 2;
|
||||||
|
public timer: number = 0
|
||||||
|
private UdpByOneClass:UdpByOne
|
||||||
|
|
||||||
|
constructor(context: common.UIAbilityContext) {
|
||||||
|
this.getTerType(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
public receiveMsg(message: string, callBack) {
|
||||||
|
const terType = this.terType;
|
||||||
|
//TODO 临时处理关闭消息接收
|
||||||
|
this.cancelMsg(this.timer)
|
||||||
|
|
||||||
|
switch (terType) {
|
||||||
|
//一型机
|
||||||
|
case 0:
|
||||||
|
const udpClass = this.getFUdp()
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
const message = udpClass.handleMsg()
|
||||||
|
callBack && callBack(message)
|
||||||
|
}, 200)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//TODO 二型机
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
|
||||||
|
//三型机
|
||||||
|
case 2:
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
callBack && callBack(message)
|
||||||
|
}, 200)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//TODO 一体机
|
||||||
|
case 3:
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.timer
|
||||||
|
}
|
||||||
|
|
||||||
|
//取消订阅
|
||||||
|
public cancelMsg(timer: number) {
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取后置机设备类型
|
||||||
|
private async getTerType(context) {
|
||||||
|
const fileUtil = new FileUtil(context)
|
||||||
|
const config = await fileUtil.readFile(GlobalConfig.comoonfileWriteAddress + '/config/ipConfig.txt');
|
||||||
|
const result = JSON.parse(config || '{}')
|
||||||
|
//默认设置为三代机
|
||||||
|
this.terType = result.terType
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getMessage(udpClass) {
|
||||||
|
const terType = this.terType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//获取一型机单例
|
||||||
|
private getFUdp(){
|
||||||
|
if (!this.UdpByOneClass) {
|
||||||
|
this.UdpByOneClass = new UdpByOne();
|
||||||
|
}
|
||||||
|
return this.UdpByOneClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
294
entry/src/main/ets/common/rearEndUnitsTool/tool/UdpByOne.ts
Normal file
294
entry/src/main/ets/common/rearEndUnitsTool/tool/UdpByOne.ts
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
import socket from '@ohos.net.socket';
|
||||||
|
import { PLCGPSData } from '../../../mock/PLCGPSData';
|
||||||
|
import FileUtil from '../../../common/utils/File';
|
||||||
|
import { GlobalConfig } from '../../../config/index';
|
||||||
|
|
||||||
|
// import { PLCGPSData } from '../../mock';
|
||||||
|
|
||||||
|
export default class UdpByOne {
|
||||||
|
// PLC udp
|
||||||
|
private PLCUDP: any;
|
||||||
|
// PLC localIp
|
||||||
|
private LocalIp: string = '192.168.7.170';
|
||||||
|
// PLC localIpPort
|
||||||
|
private PLCLocalIpPort: string = '31012';
|
||||||
|
private OppositeIp: string = '192.168.7.124'
|
||||||
|
// PLC oppositeIpPort
|
||||||
|
private PLCOppositeIpPort: string = '30012';
|
||||||
|
// PLC消息
|
||||||
|
private PLCMsg: ArrayBuffer;
|
||||||
|
// GPS udp
|
||||||
|
private GPSUDP: any;
|
||||||
|
// GPS localIp
|
||||||
|
// GPS localIpPort
|
||||||
|
private GPSLocalIpPort: string = '31013';
|
||||||
|
// GPS oppositeIpPort
|
||||||
|
private GPSOppositeIpPort: string = '30013';
|
||||||
|
// GPS消息
|
||||||
|
private GPSMsg: any;
|
||||||
|
|
||||||
|
private timer: number;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
async init(){
|
||||||
|
const fileUtil = new FileUtil(globalThis.context)
|
||||||
|
const data = await fileUtil.readFile(GlobalConfig.comoonfileWriteAddress + '/config/ipConfig.txt');
|
||||||
|
const result = JSON.parse(data)
|
||||||
|
this.LocalIp = result.udplocalIp;
|
||||||
|
this.OppositeIp = result.udpOppositeIp;
|
||||||
|
|
||||||
|
// 初始化UDP
|
||||||
|
this.PLCUDP = socket.constructUDPSocketInstance();
|
||||||
|
// this.PLCUDP.bind(this.PLCLocalIp, this.PLCLocalIpPort);
|
||||||
|
this.PLCUDP.bind({
|
||||||
|
address: this.LocalIp, port: parseInt(this.PLCLocalIpPort), family: 1
|
||||||
|
});
|
||||||
|
this.GPSUDP = socket.constructUDPSocketInstance();
|
||||||
|
// this.GPSUDP.bind(this.GPSLocalIp, this.GPSLocalIpPort);
|
||||||
|
this.GPSUDP.bind({
|
||||||
|
address: this.LocalIp, port: parseInt(this.GPSLocalIpPort), family: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
this.PLCUDP.on("message", (res, remoteInfo) => {
|
||||||
|
this.PLCMsg = res.message;
|
||||||
|
})
|
||||||
|
|
||||||
|
this.GPSUDP.on("message", (res1, remoteInfo) => {
|
||||||
|
let dataView = new DataView(res1.message)
|
||||||
|
let str = ""
|
||||||
|
for (let i = 0; i < dataView?.byteLength; ++i) {
|
||||||
|
let c = String.fromCharCode(dataView?.getUint8(i))
|
||||||
|
if (c !== "\n") {
|
||||||
|
str += c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.GPSMsg = str;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 重新绑定
|
||||||
|
public rebind() {
|
||||||
|
this.PLCUDP.bind(this.LocalIp, this.PLCLocalIpPort);
|
||||||
|
this.GPSUDP.bind(this.LocalIp, this.GPSLocalIpPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PLC发送消息
|
||||||
|
public sendPLCMsg(msg: string) {
|
||||||
|
this.PLCUDP.send({
|
||||||
|
data: '111111',
|
||||||
|
address: {
|
||||||
|
address: this.OppositeIp,
|
||||||
|
port: parseInt(this.PLCOppositeIpPort),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPS发送消息
|
||||||
|
public sendGPSMsg(msg: string) {
|
||||||
|
this.GPSUDP.send({
|
||||||
|
data: '111111',
|
||||||
|
address: {
|
||||||
|
address: this.OppositeIp,
|
||||||
|
port: parseInt(this.GPSOppositeIpPort),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接受消息
|
||||||
|
public receiveMsg(callback):number {
|
||||||
|
//TODO 临时处理关闭消息接收
|
||||||
|
this.cancelMsg(this.timer)
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
let newMessage = this.handleMsg()
|
||||||
|
callback(newMessage)
|
||||||
|
}, 200)
|
||||||
|
return this.timer
|
||||||
|
}
|
||||||
|
|
||||||
|
//取消订阅
|
||||||
|
public cancelMsg(timer:number){
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 处理消息
|
||||||
|
public handleMsg() {
|
||||||
|
let newMessage = PLCGPSData;
|
||||||
|
if (this.GPSMsg) {
|
||||||
|
// 使用正则表达式提取$GPGGA消息
|
||||||
|
let GPGGAMsg = this.GPSMsg.match(/\$GPGGA[^$]*/)[0];
|
||||||
|
let GPGGAMsgArr = GPGGAMsg ? GPGGAMsg?.split(",").slice(0, 15) : [];
|
||||||
|
// 使用正则提取$GPRMC消息
|
||||||
|
let GPRMCMsg = this.GPSMsg.match(/\$GPRMC[^$]*/)[0];
|
||||||
|
let GPRMCMsgArr = GPRMCMsg ? GPRMCMsg?.split(",").slice(0, 14) : [];
|
||||||
|
// 使用正则表达式提取$GPGST消息
|
||||||
|
let GPGSTMatch = this.GPSMsg.match(/\$GPGST[^$]*/);
|
||||||
|
let GPGSTMsgArr = GPGSTMatch ? GPGSTMatch[0]?.split(",").slice(0, 9) : [];
|
||||||
|
// 使用正则提取$PTNL消息
|
||||||
|
let PTNLMsg = this.GPSMsg.match(/\$PTNL[^$]*/)[0];
|
||||||
|
let PTNLMsgArr = PTNLMsg.split(",")?.slice(0, 14);
|
||||||
|
|
||||||
|
// 组合GPS数据
|
||||||
|
// 状态83
|
||||||
|
newMessage[83] = GPGGAMsgArr[6];
|
||||||
|
// 收星数84
|
||||||
|
newMessage[84] = GPGGAMsgArr[7];
|
||||||
|
// 海拔高85
|
||||||
|
newMessage[80] = GPGGAMsgArr[9];
|
||||||
|
// 高度差86
|
||||||
|
// 龄期87
|
||||||
|
newMessage[87] = GPGGAMsgArr[13];
|
||||||
|
// 维度因子88
|
||||||
|
// 经度因子89
|
||||||
|
// 航向角90
|
||||||
|
newMessage[90] = PTNLMsgArr[3];
|
||||||
|
// 俯仰角91
|
||||||
|
newMessage[91] = PTNLMsgArr[5];
|
||||||
|
// 航向角状态-收星数92
|
||||||
|
newMessage[92] = PTNLMsgArr[10] + '-' + PTNLMsgArr[12].split('*')[0];
|
||||||
|
// 年月日93 RMCMsgArr[9]为ddmmyy 日月年 转换为年月日
|
||||||
|
newMessage[93] =
|
||||||
|
GPRMCMsgArr[9].slice(0, 2) + GPRMCMsgArr[9].slice(2, 4) + GPRMCMsgArr[9].slice(4, 6);
|
||||||
|
// 时分秒94 GPGGAMsgArr[1]为021126.00去掉小数点后的时间
|
||||||
|
newMessage[94] = GPGGAMsgArr[1].replace(".", "");
|
||||||
|
// 经度95
|
||||||
|
newMessage[95] = GPGGAMsgArr[4];
|
||||||
|
// 纬度96
|
||||||
|
newMessage[96] = GPGGAMsgArr[2];
|
||||||
|
// 速度97
|
||||||
|
newMessage[97] = GPRMCMsgArr[7];
|
||||||
|
}
|
||||||
|
if (this.PLCMsg) {
|
||||||
|
let dataView = new DataView(this.PLCMsg)
|
||||||
|
let PLCByteArr = []
|
||||||
|
for (let i = 0; i < dataView?.byteLength; ++i) {
|
||||||
|
let c = dataView?.getUint8(i).toString(2).padStart(8, "0")
|
||||||
|
PLCByteArr.push(c.toString())
|
||||||
|
}
|
||||||
|
if (PLCByteArr.length < 55) {
|
||||||
|
return newMessage.join(",")
|
||||||
|
}
|
||||||
|
// 左方向灯 2
|
||||||
|
newMessage[2] = PLCByteArr[6][5];
|
||||||
|
// 右方向灯 3 .
|
||||||
|
newMessage[3] = PLCByteArr[6][4];
|
||||||
|
// 喇叭 4
|
||||||
|
newMessage[4] = PLCByteArr[8][4];
|
||||||
|
// 点火1 5
|
||||||
|
newMessage[5] = PLCByteArr[8][7];
|
||||||
|
// 点火2 6
|
||||||
|
newMessage[6] = PLCByteArr[8][6];
|
||||||
|
// 近光灯 7
|
||||||
|
newMessage[7] = PLCByteArr[6][7];
|
||||||
|
// 远光灯 8
|
||||||
|
newMessage[8] = PLCByteArr[6][6];
|
||||||
|
// 示廓灯 9
|
||||||
|
newMessage[9] = PLCByteArr[6][2];
|
||||||
|
// 雾灯 10
|
||||||
|
// 雨刮器 11
|
||||||
|
newMessage[11] = PLCByteArr[8][5];
|
||||||
|
// 脚刹 12
|
||||||
|
newMessage[12] = PLCByteArr[7][5];
|
||||||
|
// 手刹 13
|
||||||
|
newMessage[13] = PLCByteArr[7][4];
|
||||||
|
// 主驾驶门 14
|
||||||
|
newMessage[14] = PLCByteArr[7][7];
|
||||||
|
// NC 15
|
||||||
|
// TODO
|
||||||
|
// SA15 16
|
||||||
|
// TODO
|
||||||
|
// 离合 17
|
||||||
|
newMessage[17] = PLCByteArr[7][6];
|
||||||
|
// 副刹车 18
|
||||||
|
newMessage[18] = PLCByteArr[7][3];
|
||||||
|
// 安全带 19
|
||||||
|
newMessage[19] = PLCByteArr[7][0];
|
||||||
|
// 双跳灯 20
|
||||||
|
newMessage[20] = PLCByteArr[6][3];
|
||||||
|
// 其他门 21
|
||||||
|
// TODO
|
||||||
|
// 转速过高 22
|
||||||
|
newMessage[22] = PLCByteArr[9][0];
|
||||||
|
// 车速 23
|
||||||
|
newMessage[23] = parseInt(PLCByteArr[11], 2)+'';
|
||||||
|
// 累计脉冲 24
|
||||||
|
let Data25 = parseInt(PLCByteArr[25], 2);
|
||||||
|
let Data26 = parseInt(PLCByteArr[26], 2);
|
||||||
|
let Data27 = parseInt(PLCByteArr[27], 2);
|
||||||
|
let Data28 = parseInt(PLCByteArr[28], 2);
|
||||||
|
newMessage[24] = ((Data25 << 24) + (Data26 << 16) + (Data27 << 8) + Data28).toString();
|
||||||
|
// 发动机转速 25
|
||||||
|
let Data29 = parseInt(PLCByteArr[29], 2);
|
||||||
|
let Data30 = parseInt(PLCByteArr[30], 2);
|
||||||
|
let Data31 = parseInt(PLCByteArr[31], 2);
|
||||||
|
let Data32 = parseInt(PLCByteArr[32], 2);
|
||||||
|
newMessage[25] = ((Data29 << 24) + (Data30 << 16) + (Data31 << 8) + Data32).toString();
|
||||||
|
// 熄火次数 26
|
||||||
|
newMessage[26] = parseInt(PLCByteArr[33], 2) + '';
|
||||||
|
// 方向盘角度 27
|
||||||
|
// TODO 档位 磁档位为外接信号
|
||||||
|
newMessage[28] = globalThis.chuankoMsg == '0'?(parseInt(PLCByteArr[13], 2) + ''): globalThis.chuankoMsg;
|
||||||
|
|
||||||
|
// newMessage[27] = globalThis.chuankoMsg
|
||||||
|
// 超声波1 29
|
||||||
|
newMessage[29] = (PLCByteArr[4][1] >0 ? '300' : '1200')
|
||||||
|
// 超声波2 30
|
||||||
|
newMessage[30] = (PLCByteArr[4][0] >0 ? '300': '1200' )
|
||||||
|
|
||||||
|
//TODO 超声波3 临时写死
|
||||||
|
newMessage[31] = '1200'
|
||||||
|
//TODO 超声波4 临时写死
|
||||||
|
newMessage[32] = '1200'
|
||||||
|
// 触摸1 33
|
||||||
|
// 触摸2 34
|
||||||
|
// 触摸3 35
|
||||||
|
// SCIO 36
|
||||||
|
// SC1A_C 37
|
||||||
|
// SC1B_C 38
|
||||||
|
// SC2A_C 39
|
||||||
|
// SC2B_C 40
|
||||||
|
// SC3A_C 41
|
||||||
|
// SC3B_C 42
|
||||||
|
// SC4A_C 43
|
||||||
|
// SC4B_C 44
|
||||||
|
// SC5A_C 45
|
||||||
|
// SC5B_C 46
|
||||||
|
// SC6A_C 47
|
||||||
|
// SC6B_C 48
|
||||||
|
// 发送次数 49
|
||||||
|
// 方向盘类型 50
|
||||||
|
// 汽车类型 51
|
||||||
|
// 接口心跳 52
|
||||||
|
// 本机IP 53
|
||||||
|
// 固件版本 54
|
||||||
|
// 按键数值 55
|
||||||
|
// GPS板卡类型 56
|
||||||
|
// GPS板卡软件版本 57
|
||||||
|
// 改正数次数/改正数大小 58
|
||||||
|
// GPS数据次数/数据长度 59
|
||||||
|
// GPS错误次数 60
|
||||||
|
// 已工作时长/设定的工作时长 61
|
||||||
|
// 改正数数据长度*数据长度-基准站RTCM改正数类型 62
|
||||||
|
}
|
||||||
|
return newMessage.join(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PLC接收消息
|
||||||
|
public receivePLCMsg() {
|
||||||
|
this.PLCUDP.on("message", (message, remoteInfo) => {
|
||||||
|
console.log(`PLC receive message from ${remoteInfo.address}:${remoteInfo.port} : ${message}`);
|
||||||
|
this.PLCMsg = message;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPS接收消息
|
||||||
|
public receiveGPSMsg() {
|
||||||
|
this.GPSUDP.on("message", (message, remoteInfo) => {
|
||||||
|
console.log(`GPS receive message from ${remoteInfo.address}:${remoteInfo.port} : ${message}`);
|
||||||
|
this.GPSMsg = message;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,7 +24,6 @@ export default class GetDistance {
|
|||||||
const {fileUtil} = this
|
const {fileUtil} = this
|
||||||
const time = await getCurrentTime()
|
const time = await getCurrentTime()
|
||||||
const folderPath = await fileUtil.initFolder(`/车辆行驶距离统计`);
|
const folderPath = await fileUtil.initFolder(`/车辆行驶距离统计`);
|
||||||
// console.info('surenjun folderPath=>' ,folderPath);
|
|
||||||
const date = time.split(' ')[0].split('-').join('_')
|
const date = time.split(' ')[0].split('-').join('_')
|
||||||
const timeStr = time.split(' ')[1]
|
const timeStr = time.split(' ')[1]
|
||||||
this.timeStr = timeStr
|
this.timeStr = timeStr
|
||||||
@ -41,15 +40,11 @@ export default class GetDistance {
|
|||||||
// 过程文件数据
|
// 过程文件数据
|
||||||
public setTimeData = async (str:number) => {
|
public setTimeData = async (str:number) => {
|
||||||
const {fileUtil,folderPath,timeStr,date,totalDistance} = this;
|
const {fileUtil,folderPath,timeStr,date,totalDistance} = this;
|
||||||
// console.log('folderPath',folderPath)
|
|
||||||
const content = await fileUtil.readFile(`${folderPath}/${date}.txt`) || '';
|
const content = await fileUtil.readFile(`${folderPath}/${date}.txt`) || '';
|
||||||
const contentArr = content.split('\n').filter(item => item)
|
const contentArr = content.split('\n').filter(item => item)
|
||||||
// console.info('surenjun contentArr',JSON.stringify(contentArr))
|
|
||||||
this.totalDistance += (str * 1 > 200 ? 200 : str*1)
|
this.totalDistance += (str * 1 > 200 ? 200 : str*1)
|
||||||
this.totalTime += 1;
|
this.totalTime += 1;
|
||||||
contentArr[contentArr.length - 1] = `程序启动时间:${timeStr} 累计行驶距离:${(this.totalDistance).toFixed(2)}m 累计运行时常:${Math.ceil(this.totalTime/60)}min`+ '\n'
|
contentArr[contentArr.length - 1] = `程序启动时间:${timeStr} 累计行驶距离:${(this.totalDistance).toFixed(2)}m 累计运行时常:${Math.ceil(this.totalTime/60)}min`+ '\n'
|
||||||
console.info('surenjun',contentArr.join('\n'))
|
|
||||||
// console.log('folderPath',folderPath,date)
|
|
||||||
this.uploadData()
|
this.uploadData()
|
||||||
|
|
||||||
// await fileUtil.addFile(
|
// await fileUtil.addFile(
|
||||||
|
|||||||
@ -16,7 +16,8 @@ export async function getTCP(flag=false) {
|
|||||||
globalThis.TcpClient.onMessage = () => {
|
globalThis.TcpClient.onMessage = () => {
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
const result=JSON.parse(data)
|
const result = JSON.parse(data)
|
||||||
|
const terType = result.terType
|
||||||
if (globalThis.TcpClient && globalThis.TcpClient.closeTcp&&!flag) {
|
if (globalThis.TcpClient && globalThis.TcpClient.closeTcp&&!flag) {
|
||||||
globalThis.TcpClient.closeTcp(async () => {
|
globalThis.TcpClient.closeTcp(async () => {
|
||||||
// const tcpClient: TcpClient =new TcpClient(result[0].tcplocalIp, result[0].tcplocalIpPort,result[0].tcpOppositeIp,result[0].tcpOppositePort)
|
// const tcpClient: TcpClient =new TcpClient(result[0].tcplocalIp, result[0].tcplocalIpPort,result[0].tcpOppositeIp,result[0].tcpOppositePort)
|
||||||
@ -48,7 +49,7 @@ export async function getTCP(flag=false) {
|
|||||||
if (val) {
|
if (val) {
|
||||||
// const msg=val.substring(5,val.length-1)
|
// const msg=val.substring(5,val.length-1)
|
||||||
console.log('socketTag[PLC.UdpClient] status:', globalThis.udpClient.getStatus())
|
console.log('socketTag[PLC.UdpClient] status:', globalThis.udpClient.getStatus())
|
||||||
gpsTcpClient.sendGpsMsg(val)
|
terType == 0?gpsTcpClient.sendGpsMsg(val): globalThis.udpClient?.sendMsg(val)
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ export async function getTCP(flag=false) {
|
|||||||
await globalThis.TcpClient.onMessage((val) => {
|
await globalThis.TcpClient.onMessage((val) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (val && globalThis.udpClient?.sendMsg) {
|
if (val && globalThis.udpClient?.sendMsg) {
|
||||||
gpsTcpClient.sendGpsMsg(val)
|
terType == 0?gpsTcpClient.sendGpsMsg(val): globalThis.udpClient?.sendMsg(val)
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
|
|||||||
@ -370,6 +370,16 @@ export async function setJudgeUdp() {
|
|||||||
})
|
})
|
||||||
console.info('surenjun', `考车发送确定扣分指令,指令为:${directives}`)
|
console.info('surenjun', `考车发送确定扣分指令,指令为:${directives}`)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//申请语音对讲
|
||||||
|
askVoice(){
|
||||||
|
globalThis.udpClient2.sendMsgExt({
|
||||||
|
id: 49,
|
||||||
|
list: [],
|
||||||
|
carNo: globalThis.carInfo.carNo,
|
||||||
|
placeId: globalThis.carInfo.examinationRoomId,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,8 +19,7 @@ import FileUtil from '../../common/utils/File';
|
|||||||
import prompt from '@ohos.prompt';
|
import prompt from '@ohos.prompt';
|
||||||
import promptAction from '@ohos.promptAction';
|
import promptAction from '@ohos.promptAction';
|
||||||
import { getUDP } from './GlobalUdp';
|
import { getUDP } from './GlobalUdp';
|
||||||
import UdpByOne from './UdpByOne';
|
import RearEndUnitsTool from '../rearEndUnitsTool/index'
|
||||||
|
|
||||||
const TAG = '[UdpDemo.UdpClient]'
|
const TAG = '[UdpDemo.UdpClient]'
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +46,7 @@ export default class UdpClientByCenter {
|
|||||||
private isWorking: Boolean = false
|
private isWorking: Boolean = false
|
||||||
private plcUdpError = false;
|
private plcUdpError = false;
|
||||||
private initParam
|
private initParam
|
||||||
private UPDOne: any
|
private retClass: RearEndUnitsTool
|
||||||
|
|
||||||
constructor(udplocalIp: string, udplocalIpPort: string, udpOppositeIp: string, udpOppositeIpPort: string) {
|
constructor(udplocalIp: string, udplocalIpPort: string, udpOppositeIp: string, udpOppositeIpPort: string) {
|
||||||
this.localIp = udplocalIp
|
this.localIp = udplocalIp
|
||||||
@ -58,7 +57,7 @@ export default class UdpClientByCenter {
|
|||||||
}
|
}
|
||||||
this.udp = socket.constructUDPSocketInstance();
|
this.udp = socket.constructUDPSocketInstance();
|
||||||
this.initPath()
|
this.initPath()
|
||||||
this.UPDOne = new UdpByOne()
|
this.retClass = new RearEndUnitsTool(globalThis.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatus() {
|
getStatus() {
|
||||||
@ -302,7 +301,9 @@ export default class UdpClientByCenter {
|
|||||||
//plc
|
//plc
|
||||||
onMessage_1(callback?) {
|
onMessage_1(callback?) {
|
||||||
this.onMessage_1Callback = callback;
|
this.onMessage_1Callback = callback;
|
||||||
this.UPDOne.receiveMsg(callback);
|
// const udpMsg = this.UPDOne.receiveMsg(callback);
|
||||||
|
this.retClass.receiveMsg(this.currentValue,callback)
|
||||||
|
// this.udp && this.udp.on('message', this.message_1Fn);
|
||||||
// this.udp && this.udp.on('message', this.message_1Fn);
|
// this.udp && this.udp.on('message', this.message_1Fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +351,7 @@ export default class UdpClientByCenter {
|
|||||||
globalThis.dialogOpen = false
|
globalThis.dialogOpen = false
|
||||||
this.chafenFlag = 0
|
this.chafenFlag = 0
|
||||||
}
|
}
|
||||||
callback && callback(newArr.toString())
|
// callback && callback(newArr.toString())
|
||||||
this.currentValue = newArr.toString();
|
this.currentValue = newArr.toString();
|
||||||
} else {
|
} else {
|
||||||
callback && callback('')
|
callback && callback('')
|
||||||
|
|||||||
@ -57,13 +57,14 @@ export const getMessageHeartbeat = async (msg) => {
|
|||||||
const carInfo = globalThis.carInfo;
|
const carInfo = globalThis.carInfo;
|
||||||
const { examSubject,plateNo } = carInfo;
|
const { examSubject,plateNo } = carInfo;
|
||||||
const ksyh='0000000000000'
|
const ksyh='0000000000000'
|
||||||
|
'0000000000000'
|
||||||
const {fourInOneScreen:{gpsDigit}} = judgeConfig
|
const {fourInOneScreen:{gpsDigit}} = judgeConfig
|
||||||
const asclshArr = stringToASC(fillZero(
|
const asclshArr = stringToASC(fillZero(
|
||||||
globalThis.singlePlay
|
globalThis.singlePlay
|
||||||
? (examSubject == 2 ? '0000000000000' : '0000000000000')
|
? (examSubject == 2 ? '0000000000000' : '0000000000000')
|
||||||
: '11111111111',
|
: globalThis.lsh,
|
||||||
13));
|
13));
|
||||||
const ascksyhArr = stringToASC(fillZero(examSubject == 2 ? '0000000000000':'1111111111111', 13))
|
const ascksyhArr = stringToASC(fillZero(ksyh, 13))
|
||||||
const ascsbxhArr = stringToASC('00000000')
|
const ascsbxhArr = stringToASC('00000000')
|
||||||
// const ascsbxhArr = stringToASC('153216400880')
|
// const ascsbxhArr = stringToASC('153216400880')
|
||||||
const serialIndex = globalThis.serialIndex
|
const serialIndex = globalThis.serialIndex
|
||||||
|
|||||||
@ -193,6 +193,11 @@ struct Index {
|
|||||||
this.syssetParam623 = value == '1'?true:false
|
this.syssetParam623 = value == '1'?true:false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//386 触发模拟灯光条件
|
||||||
|
if(sys.v_no == '386'){
|
||||||
|
this.syssetParam386 = value
|
||||||
|
}
|
||||||
|
|
||||||
//科目三应行驶距离参数
|
//科目三应行驶距离参数
|
||||||
if (sys.v_no == '303') {
|
if (sys.v_no == '303') {
|
||||||
this.examMileage = this.examMileage == '0'?(sys.v_value + ''): this.examMileage;
|
this.examMileage = this.examMileage == '0'?(sys.v_value + ''): this.examMileage;
|
||||||
@ -549,6 +554,16 @@ struct Index {
|
|||||||
await this.initSysset(initDataObj.sysset);
|
await this.initSysset(initDataObj.sysset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭人工扣分弹窗
|
||||||
|
async closeDeductedPop(){
|
||||||
|
this.isDeductedPopShow = false;
|
||||||
|
this.defaultTabIndex = 0;
|
||||||
|
if(this.syssetParam386 == '3' && !this.syssetParam386ET3){
|
||||||
|
this.judge.rmndg = 2;
|
||||||
|
this.syssetParam386ET3 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 上传考试里程
|
// 上传考试里程
|
||||||
async uploadMileage(){
|
async uploadMileage(){
|
||||||
if(!globalThis.singlePlay){
|
if(!globalThis.singlePlay){
|
||||||
@ -919,10 +934,7 @@ struct Index {
|
|||||||
return project.type == '2' ? project.projectCode : undefined
|
return project.type == '2' ? project.projectCode : undefined
|
||||||
}).filter(project => project !== undefined),
|
}).filter(project => project !== undefined),
|
||||||
markRules: this.manualMarkRules,
|
markRules: this.manualMarkRules,
|
||||||
closePopup: () => {
|
closePopup: ()=>{this.closeDeductedPop()},
|
||||||
this.isDeductedPopShow = false;
|
|
||||||
this.defaultTabIndex = 0;
|
|
||||||
},
|
|
||||||
confirmMark: async (itemno, serial)=>{
|
confirmMark: async (itemno, serial)=>{
|
||||||
clearTimeout(this.popTimer)
|
clearTimeout(this.popTimer)
|
||||||
this.popTimer = null
|
this.popTimer = null
|
||||||
@ -1364,6 +1376,9 @@ struct Index {
|
|||||||
@State serialNumber: number = 0
|
@State serialNumber: number = 0
|
||||||
@State syssetParam623: boolean = false;
|
@State syssetParam623: boolean = false;
|
||||||
@State syssetParam211: string = '';
|
@State syssetParam211: string = '';
|
||||||
|
//模拟灯光触发条件
|
||||||
|
@State syssetParam386: string = '';
|
||||||
|
@State syssetParam386ET3: boolean = false;
|
||||||
@State carType: string = ''
|
@State carType: string = ''
|
||||||
@State carName: string = ''
|
@State carName: string = ''
|
||||||
@State isDeductedPopShow: boolean = false
|
@State isDeductedPopShow: boolean = false
|
||||||
|
|||||||
@ -19,6 +19,8 @@ struct Index {
|
|||||||
|
|
||||||
// @State inputTextList1: string[] = ['172.37.55.191','18782','192.168.7.1','8082','255.255.255.0','192.168.7.170','114.114.114.114','192.168.7.124','20022','172.37.55.59','20122']
|
// @State inputTextList1: string[] = ['172.37.55.191','18782','192.168.7.1','8082','255.255.255.0','192.168.7.170','114.114.114.114','192.168.7.124','20022','172.37.55.59','20122']
|
||||||
@State inputTextList1: string[] = ['172.37.55.191', '18782', '172.37.55.191', '8082', '255.255.255.0', '192.168.7.1', '114.114.114.114', '192.168.7.124', '20022', '192.168.7.170', '20122']
|
@State inputTextList1: string[] = ['172.37.55.191', '18782', '172.37.55.191', '8082', '255.255.255.0', '192.168.7.1', '114.114.114.114', '192.168.7.124', '20022', '192.168.7.170', '20122']
|
||||||
|
@State terTextList: string[] = ['一型机', '二型机', '三型机', '一体机']
|
||||||
|
@State selectedTerType: number = 0
|
||||||
// @State inputTextList2: string[] = []
|
// @State inputTextList2: string[] = []
|
||||||
// 112.80.35.83 11052
|
// 112.80.35.83 11052
|
||||||
// @State inputTextList1: string[] = ['192.168.36.2','8084','192.168.36.200','20122','255.255.255.0','192.168.36.1','','','114.114.114.114','192.168.36.139','8000']
|
// @State inputTextList1: string[] = ['192.168.36.2','8084','192.168.36.200','20122','255.255.255.0','192.168.36.1','','','114.114.114.114','192.168.36.139','8000']
|
||||||
@ -46,7 +48,7 @@ struct Index {
|
|||||||
.fontSize(this.inputFontSize * this.ratio)
|
.fontSize(this.inputFontSize * this.ratio)
|
||||||
TextInput({ 'text': this.inputTextList1[index] ? this.inputTextList1[index] : '' })
|
TextInput({ 'text': this.inputTextList1[index] ? this.inputTextList1[index] : '' })
|
||||||
.width('50%')
|
.width('50%')
|
||||||
.height('60%')
|
.height('50%')
|
||||||
.fontColor('#fff')
|
.fontColor('#fff')
|
||||||
.borderColor('#E6E0D8')
|
.borderColor('#E6E0D8')
|
||||||
.borderRadius('10px')
|
.borderRadius('10px')
|
||||||
@ -62,25 +64,46 @@ struct Index {
|
|||||||
this.inputTextList1[index] = value
|
this.inputTextList1[index] = value
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}.width('50%').height('14%')
|
||||||
.width('50%')
|
|
||||||
.height('16.7%')
|
|
||||||
})
|
|
||||||
|
|
||||||
|
})
|
||||||
|
Row() {
|
||||||
|
}.width('50%').height('14%')
|
||||||
|
|
||||||
|
Row() {
|
||||||
|
Text('后置机类型')
|
||||||
|
.width('40%')
|
||||||
|
.height('100%')
|
||||||
|
.fontColor('#E5CBA1')
|
||||||
|
.padding({ 'left': '35px' })
|
||||||
|
.fontSize(this.inputFontSize * this.ratio)
|
||||||
|
|
||||||
|
ForEach(this.terTextList, (terText, index) => {
|
||||||
|
Radio({ value: terText, group: 'radioGroup' })
|
||||||
|
.borderColor('#E5CBA1')
|
||||||
|
.checked(index === this.selectedTerType)
|
||||||
|
.onChange((value: boolean) => {
|
||||||
|
if(value){
|
||||||
|
this.selectedTerType = index
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Text(terText).fontSize(20).fontColor('#FFF')
|
||||||
|
})
|
||||||
|
}.width('50%').height('14%')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width('95%')
|
.width('95%')
|
||||||
.height('90%')
|
.height('95%')
|
||||||
.margin({ 'top': '2%' })
|
.margin({ 'top': '1%' })
|
||||||
.backgroundColor('#282828')
|
.backgroundColor('#282828')
|
||||||
.borderRadius('15px')
|
.borderRadius('15px')
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height('80%')
|
.height('85%')
|
||||||
.borderRadius('25px')
|
.borderRadius('25px')
|
||||||
|
|
||||||
Column() {
|
Column() {
|
||||||
Image($r('app.media.terminal_save')).width('20.5%').height('74%').onClick(async () => {
|
Image($r('app.media.terminal_save')).width('18%').onClick(async () => {
|
||||||
const fileUtil = new FileUtil(this.context)
|
const fileUtil = new FileUtil(this.context)
|
||||||
const folderPath = await fileUtil.initFolder(`/config`);
|
const folderPath = await fileUtil.initFolder(`/config`);
|
||||||
const param = {
|
const param = {
|
||||||
@ -96,7 +119,8 @@ struct Index {
|
|||||||
gateway: this.inputTextList1[5],
|
gateway: this.inputTextList1[5],
|
||||||
dnsServers: this.inputTextList1[6],
|
dnsServers: this.inputTextList1[6],
|
||||||
centerIp: this.inputTextList1[2],
|
centerIp: this.inputTextList1[2],
|
||||||
centerPort: this.inputTextList1[3]
|
centerPort: this.inputTextList1[3],
|
||||||
|
terType: this.selectedTerType
|
||||||
}
|
}
|
||||||
fileUtil.addFile(`${folderPath}/ipConfig.txt`, JSON.stringify(param), '')
|
fileUtil.addFile(`${folderPath}/ipConfig.txt`, JSON.stringify(param), '')
|
||||||
// upDateTableByArray('IpConfigTable',[])
|
// upDateTableByArray('IpConfigTable',[])
|
||||||
@ -128,15 +152,15 @@ struct Index {
|
|||||||
}
|
}
|
||||||
.backgroundColor('#CCC4B8')
|
.backgroundColor('#CCC4B8')
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height('20%')
|
.height('15%')
|
||||||
.borderRadius({ 'bottomLeft': '25px', 'bottomRight': '25px' })
|
.borderRadius({ 'bottomLeft': '25px', 'bottomRight': '25px' })
|
||||||
.justifyContent(FlexAlign.SpaceAround)
|
.justifyContent(FlexAlign.SpaceAround)
|
||||||
}
|
}
|
||||||
.width('75%')
|
.width('75%')
|
||||||
.height('69.4%')
|
.height('80%')
|
||||||
.backgroundColor('#E6E3DF')
|
.backgroundColor('#E6E3DF')
|
||||||
.borderRadius('25px')
|
.borderRadius('25px')
|
||||||
.margin({ 'top': '7%' })
|
.margin({ 'top': '2%' })
|
||||||
.justifyContent(FlexAlign.SpaceAround)
|
.justifyContent(FlexAlign.SpaceAround)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -168,6 +192,8 @@ struct Index {
|
|||||||
this.inputTextList1[6] = result.dnsServers
|
this.inputTextList1[6] = result.dnsServers
|
||||||
this.inputTextList1[2] = result.centerIp
|
this.inputTextList1[2] = result.centerIp
|
||||||
this.inputTextList1[3] = result.centerPort
|
this.inputTextList1[3] = result.centerPort
|
||||||
|
this.selectedTerType = result.terType
|
||||||
|
console.log('surenjun', this.selectedTerType + '');
|
||||||
}
|
}
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
|
|||||||
@ -223,6 +223,7 @@ struct UserInfo {
|
|||||||
})
|
})
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
this.currentUser = (this.list.length ? this.list[0] : EmptyCandidateObject)
|
this.currentUser = (this.list.length ? this.list[0] : EmptyCandidateObject)
|
||||||
|
globalThis.lsh = this.list.length?this.currentUser.lsh:'1111111111111'
|
||||||
}
|
}
|
||||||
} else if (user && (user.kssycs == '0' || user.kssycs == '')) {
|
} else if (user && (user.kssycs == '0' || user.kssycs == '')) {
|
||||||
console.log('datadatadatadata')
|
console.log('datadatadatadata')
|
||||||
@ -239,6 +240,7 @@ struct UserInfo {
|
|||||||
}, 200)
|
}, 200)
|
||||||
} else {
|
} else {
|
||||||
this.currentUser = EmptyCandidateObject
|
this.currentUser = EmptyCandidateObject
|
||||||
|
globalThis.lsh = '1111111111111'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.list.forEach((res, index) => {
|
this.list.forEach((res, index) => {
|
||||||
@ -1198,6 +1200,9 @@ struct UserInfo {
|
|||||||
// .commStyle()
|
// .commStyle()
|
||||||
imageBtn({ btnWidth: 220 * this.ratio, btnHeight: 69 * this.ratio, imgSrc: $r('app.media.yydj_btn') })
|
imageBtn({ btnWidth: 220 * this.ratio, btnHeight: 69 * this.ratio, imgSrc: $r('app.media.yydj_btn') })
|
||||||
.margin({ bottom: 12 * this.ratio })
|
.margin({ bottom: 12 * this.ratio })
|
||||||
|
.onClick(()=>{
|
||||||
|
globalThis.judgeUdp.askVoice()
|
||||||
|
})
|
||||||
|
|
||||||
// Image($r('app.media.gx_btn'))
|
// Image($r('app.media.gx_btn'))
|
||||||
// .commStyle()
|
// .commStyle()
|
||||||
|
|||||||
@ -293,11 +293,14 @@ export default struct SignDisplayCom {
|
|||||||
.margin({ top: 6 * this.ratio, left: 10 * this.ratio })
|
.margin({ top: 6 * this.ratio, left: 10 * this.ratio })
|
||||||
|
|
||||||
Row() {
|
Row() {
|
||||||
|
if(this.active == 1) {
|
||||||
RealTime({
|
RealTime({
|
||||||
widthNumber: Math.floor(550 * this.ratio),
|
widthNumber: Math.floor(550 * this.ratio),
|
||||||
heightNumber: Math.floor(380 * this.ratio),
|
heightNumber: Math.floor(380 * this.ratio),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
.width(550 * this.ratio)
|
.width(550 * this.ratio)
|
||||||
.height(380 * this.ratio)
|
.height(380 * this.ratio)
|
||||||
.backgroundColor('#1A1A1A')
|
.backgroundColor('#1A1A1A')
|
||||||
|
|||||||
@ -275,7 +275,7 @@ export default class Judge {
|
|||||||
private modelPath: string
|
private modelPath: string
|
||||||
private avPlayer
|
private avPlayer
|
||||||
private carztStr: string
|
private carztStr: string
|
||||||
private rmndg: 0 | 1
|
private rmndg: 0 | 1 | 2
|
||||||
private mndgStr: string | undefined
|
private mndgStr: string | undefined
|
||||||
// 模拟灯光
|
// 模拟灯光
|
||||||
setMndg = async (mndgStr: string) => {
|
setMndg = async (mndgStr: string) => {
|
||||||
@ -508,11 +508,14 @@ export default class Judge {
|
|||||||
if (msg.method === 'examJudgeArtificialMark') {
|
if (msg.method === 'examJudgeArtificialMark') {
|
||||||
setJudgeItem(msg.itemno, msg.serial)
|
setJudgeItem(msg.itemno, msg.serial)
|
||||||
}
|
}
|
||||||
|
msg.sensor.rmndg = this.rmndg
|
||||||
|
await fileLog.setExamJudgeData(msg)
|
||||||
await examJudgeRealExam(msg)
|
await examJudgeRealExam(msg)
|
||||||
|
this.rmndg = 0
|
||||||
const bytes = await this.getMessageHeartbeat();
|
const bytes = await this.getMessageHeartbeat();
|
||||||
bytes && globalThis.judgeUdp.send(bytes)
|
bytes && globalThis.judgeUdp.send(bytes)
|
||||||
|
|
||||||
}, 200)
|
}, 50)
|
||||||
|
|
||||||
globalThis.judgeTimer = judgeTimer;
|
globalThis.judgeTimer = judgeTimer;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,12 +54,12 @@ export default class FileModel{
|
|||||||
const content = fileUtil.getFileContent(`${folderPath}/${fileName}`)
|
const content = fileUtil.getFileContent(`${folderPath}/${fileName}`)
|
||||||
return content;
|
return content;
|
||||||
}catch (e){
|
}catch (e){
|
||||||
// console.info('surenjun',JSON.stringify(e))
|
console.info('surenjun',JSON.stringify(e))
|
||||||
// promptAction.showToast({
|
// promptAction.showToast({
|
||||||
// message:`请检查模型路径${folderPath}/${fileName}是否正确!`,
|
// message:`请检查模型路径${folderPath}/${fileName}是否正确!`,
|
||||||
// duration:4000
|
// duration:4000
|
||||||
// })
|
// })
|
||||||
return ''
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -98,8 +98,6 @@ export function getKmProjectVoice(
|
|||||||
const param544Str = judgeConfig['544']?.split(',') || [];
|
const param544Str = judgeConfig['544']?.split(',') || [];
|
||||||
const param405Str = judgeConfig['405'] || 0;
|
const param405Str = judgeConfig['405'] || 0;
|
||||||
|
|
||||||
console.info('surenjun => param544Str.length',param544Str.length)
|
|
||||||
|
|
||||||
const {num,count,road} = lane
|
const {num,count,road} = lane
|
||||||
if(examSubject == 2){
|
if(examSubject == 2){
|
||||||
return projectCode
|
return projectCode
|
||||||
@ -314,8 +312,9 @@ export const plcStrToJson = async (plc:string) =>{
|
|||||||
//@ts-ignore 角度差分状态
|
//@ts-ignore 角度差分状态
|
||||||
jdzt:p[92].split('-')[0]*1,
|
jdzt:p[92].split('-')[0]*1,
|
||||||
//gps数据
|
//gps数据
|
||||||
|
//TODO 一 精度纬度要取反
|
||||||
//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],
|
sj:time, jd:p[95], wd:p[96], 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,
|
age:p[87], jdyz:p[89], wdyz:p[88], dwsxs:p[84] || 0,
|
||||||
//@ts-ignore 角度搜星数
|
//@ts-ignore 角度搜星数
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user