Compare commits
30 Commits
main
...
dev_tcp2by
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ea8e4e3e7 | ||
|
|
27db86cf2a | ||
|
|
b612c376ee | ||
| 6a2fb2e902 | |||
| 738e83c356 | |||
|
|
284532f979 | ||
| b80d575b96 | |||
|
|
4ed37ae613 | ||
| d69b2e23e0 | |||
|
|
1b2181adcc | ||
|
|
ee79034ddf | ||
| 0c32b01285 | |||
| aab38515ed | |||
| 54ad70b383 | |||
|
|
488e237b6f | ||
|
|
097711c46c | ||
|
|
32e66a83be | ||
|
|
5d367da241 | ||
| 5717c83aa7 | |||
|
|
21dec3fff1 | ||
|
|
d4188fb3d7 | ||
| 526faa97df | |||
|
|
1a890f3e96 | ||
| 9806ce8664 | |||
|
|
b966891f35 | ||
| 4d0e35c8f0 | |||
| 54e06e7742 | |||
| 7a197098aa | |||
| 0cb15e4c04 | |||
| a44e0e455e |
@ -4,13 +4,13 @@
|
|||||||
{
|
{
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"material": {
|
"material": {
|
||||||
"certpath": "/Users/surenjun/.ohos/config/openharmony/auto_ohos_default_subject-two_com.oh.dts.cer",
|
"certpath": "/Users/wangzhongjie/.ohos/config/openharmony/default_subject-two_Kl4t-ZSvZeuUm9s8O-e6FIH2VFR_OaNyhDP8kPjIWgU=.cer",
|
||||||
"storePassword": "0000001BE4BBADDF656A884E7A7BB5FD51F64FBB61DD24A944FEA969482DD693210ED5FF3D29F13642E3A3",
|
"storePassword": "0000001B1A6C605B348CE1F76970E037662E7240FC9A88762FF9CC0FBF41CD85BB9F44F66A7002A0A4226D",
|
||||||
"keyAlias": "debugKey",
|
"keyAlias": "debugKey",
|
||||||
"keyPassword": "0000001BDEFFDC280B45617E7FC447CB21F2D133540301F543454643D3F5E9F6E5ED2A583A7FA92B260433",
|
"keyPassword": "0000001B0C7AC8946180EE4BBCB5880D04DF499C741EBA9485672DD1C6902D3944018F866199FFD1B10B30",
|
||||||
"profile": "/Users/surenjun/.ohos/config/openharmony/auto_ohos_default_subject-two_com.oh.dts.p7b",
|
"profile": "/Users/wangzhongjie/.ohos/config/openharmony/default_subject-two_Kl4t-ZSvZeuUm9s8O-e6FIH2VFR_OaNyhDP8kPjIWgU=.p7b",
|
||||||
"signAlg": "SHA256withECDSA",
|
"signAlg": "SHA256withECDSA",
|
||||||
"storeFile": "/Users/surenjun/.ohos/config/openharmony/auto_ohos_default_subject-two_com.oh.dts.p12"
|
"storeFile": "/Users/wangzhongjie/.ohos/config/openharmony/default_subject-two_Kl4t-ZSvZeuUm9s8O-e6FIH2VFR_OaNyhDP8kPjIWgU=.p12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -2,6 +2,11 @@
|
|||||||
"apiType": 'stageMode',
|
"apiType": 'stageMode',
|
||||||
"buildOption": {
|
"buildOption": {
|
||||||
"externalNativeOptions": {
|
"externalNativeOptions": {
|
||||||
|
"abiFilters": [
|
||||||
|
"arm64-v8a",
|
||||||
|
"armeabi-v7a",
|
||||||
|
"x86_64"
|
||||||
|
],
|
||||||
"path": "./src/main/cpp/CMakeLists.txt",
|
"path": "./src/main/cpp/CMakeLists.txt",
|
||||||
"arguments": "",
|
"arguments": "",
|
||||||
"cppFlags": "",
|
"cppFlags": "",
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 2,
|
||||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||||
"specifiers": {
|
"specifiers": {
|
||||||
"@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6"
|
"@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6"
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ohos/hypium@1.0.6": {
|
"@ohos/hypium@1.0.6": {
|
||||||
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
|
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
|
||||||
"integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ=="
|
"integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ==",
|
||||||
|
"registryType": "ohpm",
|
||||||
|
"shasum": "3f5fed65372633233264b3447705b0831dfe7ea1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,7 +3,7 @@ import request from "../common/utils/request"
|
|||||||
let baseHost = globalThis.host;
|
let baseHost = globalThis.host;
|
||||||
import FileUtil from '../common/utils/File';
|
import FileUtil from '../common/utils/File';
|
||||||
import FileLog from '../pages/judgeSDK/utils/fileLog';
|
import FileLog from '../pages/judgeSDK/utils/fileLog';
|
||||||
|
import tcp2ByteRequest from '../tcp2byte/index'
|
||||||
//监管接口序列号映射
|
//监管接口序列号映射
|
||||||
const gjxlhObj = {
|
const gjxlhObj = {
|
||||||
'17C51': '02-21-000009',
|
'17C51': '02-21-000009',
|
||||||
@ -26,6 +26,11 @@ export default async function writeObjectOutNew(data,filePath): Promise<WR> {
|
|||||||
const params = await getParams(jkid, drvexam);
|
const params = await getParams(jkid, drvexam);
|
||||||
const {wglb,jkxlh,glbm,jgbh,sjbs} = basic;
|
const {wglb,jkxlh,glbm,jgbh,sjbs} = basic;
|
||||||
|
|
||||||
|
const reqData = {
|
||||||
|
wglb,jkxlh,glbm,jgbh,sjbs,
|
||||||
|
data:params.data,
|
||||||
|
file:params.file
|
||||||
|
}
|
||||||
if(filePath){
|
if(filePath){
|
||||||
await fileUtil.editFile(`${filePath}/wuxi_exam_data.txt`,JSON.stringify({
|
await fileUtil.editFile(`${filePath}/wuxi_exam_data.txt`,JSON.stringify({
|
||||||
wglb,jkxlh,glbm,jgbh,sjbs,
|
wglb,jkxlh,glbm,jgbh,sjbs,
|
||||||
@ -38,36 +43,12 @@ export default async function writeObjectOutNew(data,filePath): Promise<WR> {
|
|||||||
console.info('surenjun','调用新监管')
|
console.info('surenjun','调用新监管')
|
||||||
let temp
|
let temp
|
||||||
try {
|
try {
|
||||||
temp = await request({
|
temp = await tcp2ByteRequest(reqData)
|
||||||
host: globalThis.JGHOST,
|
}catch (e){
|
||||||
method: 'post',
|
|
||||||
//是否是新中心
|
|
||||||
isNewCenter: true,
|
|
||||||
xml: true,
|
|
||||||
url: '/dems_ws/services/TmriOutAccess?wsdl',
|
|
||||||
data: `<?xml version="1.0"?>
|
|
||||||
<SOAP-ENV:Envelope
|
|
||||||
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
|
||||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
|
||||||
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
>
|
|
||||||
<SOAP-ENV:Body>
|
|
||||||
<writeObjectOut xmlns="http://service.es.doron">
|
|
||||||
<wglb>${wglb}</wglb>
|
|
||||||
<jkxlh>${jkxlh}</jkxlh>
|
|
||||||
<glbm>${glbm}</glbm>
|
|
||||||
<jgbh>${jgbh}</jgbh>
|
|
||||||
<sjbs>${sjbs}</sjbs>
|
|
||||||
<data>${JSON.stringify(params.data)}</data>
|
|
||||||
<file>${JSON.stringify(params.file)}</file>
|
|
||||||
</writeObjectOut>
|
|
||||||
</SOAP-ENV:Body>
|
|
||||||
</SOAP-ENV:Envelope>`,
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
console.log("新监管错误")
|
console.log("新监管错误")
|
||||||
temp = e
|
temp = e
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("temp message: ", JSON.stringify(temp))
|
console.log("temp message: ", JSON.stringify(temp))
|
||||||
if(filePath){
|
if(filePath){
|
||||||
await fileUtil.editFile(`${filePath}/wuxi_exam_data.txt`,JSON.stringify(temp) +`\n`);
|
await fileUtil.editFile(`${filePath}/wuxi_exam_data.txt`,JSON.stringify(temp) +`\n`);
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export const GlobalConfig={
|
|||||||
//杭州
|
//杭州
|
||||||
hz:{
|
hz:{
|
||||||
km2:['2022.03.14.01','2022.03.17.1'],
|
km2:['2022.03.14.01','2022.03.17.1'],
|
||||||
km3:[],
|
km3:['2024.08.21.01','2024.08.24.1'],
|
||||||
},
|
},
|
||||||
//黑龙江
|
//黑龙江
|
||||||
hlg:{
|
hlg:{
|
||||||
|
|||||||
211
entry/src/main/ets/tcp2byte/index.ts
Normal file
211
entry/src/main/ets/tcp2byte/index.ts
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import socket from '@ohos.net.socket'
|
||||||
|
import util from '@ohos.util'
|
||||||
|
import promptAction from '@ohos.promptAction'
|
||||||
|
import TcpToByte from './utils/tcp2byte'
|
||||||
|
import { bytesToDecimal } from './utils/tools'
|
||||||
|
|
||||||
|
const TAG = '[TCP2BYTE]'
|
||||||
|
|
||||||
|
|
||||||
|
interface RES {
|
||||||
|
code: number | string,
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
address: '172.37.55.191',
|
||||||
|
port: 40000
|
||||||
|
}
|
||||||
|
|
||||||
|
const singleTcpClient = (function () {
|
||||||
|
let instance;
|
||||||
|
|
||||||
|
function createInstance() {
|
||||||
|
return socket.constructTCPSocketInstance()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getClient: function () {
|
||||||
|
if (!instance) {
|
||||||
|
instance = createInstance();
|
||||||
|
}
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default async function tcp2ByteRequest(data): Promise<RES> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const tcpClient: socket.TCPSocket = singleTcpClient.getClient();
|
||||||
|
const { address, port } = config;
|
||||||
|
const tcp2Byte = new TcpToByte();
|
||||||
|
const sendData = tcp2Byte.getRequest(data);
|
||||||
|
console.info(TAG, 'sendData=>' + JSON.stringify(sendData));
|
||||||
|
|
||||||
|
// 设置超时时间(例如 10 秒)
|
||||||
|
const timeoutDuration = 15000; // 10 秒
|
||||||
|
let timeoutHandle: number | null = null;
|
||||||
|
|
||||||
|
// 超时处理函数
|
||||||
|
const timeoutPromise = new Promise<RES>((_, rejectTimeout) => {
|
||||||
|
timeoutHandle = setTimeout(() => {
|
||||||
|
const errMsg = 'TCP request timed out';
|
||||||
|
console.log(TAG, "超时", errMsg);
|
||||||
|
promptAction.showToast({
|
||||||
|
message: errMsg,
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
tcpClient.close();
|
||||||
|
rejectTimeout(new Error(errMsg));
|
||||||
|
}, timeoutDuration);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await tcpClient.connect({
|
||||||
|
address: {
|
||||||
|
address,
|
||||||
|
port,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
handSendMessage(tcpClient, data.sjbs, sendData);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(TAG, 'tcp client connect error' + JSON.stringify(e));
|
||||||
|
promptAction.showToast({
|
||||||
|
message: 'tcp client connect error' + JSON.stringify(e),
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
reject(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收到消息
|
||||||
|
tcpClient.on('message', (data) => {
|
||||||
|
const res = handReceiveMessage(tcpClient, sendData, data.message);
|
||||||
|
if (res) {
|
||||||
|
if (timeoutHandle) clearTimeout(timeoutHandle); // 清除超时
|
||||||
|
tcpClient.close();
|
||||||
|
resolve(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tcpClient.on('error', (e) => {
|
||||||
|
const errMsg = 'tcp client receive error' + JSON.stringify(e);
|
||||||
|
promptAction.showToast({
|
||||||
|
message: 'tcp client receive error' + JSON.stringify(e),
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
console.log(TAG, errMsg);
|
||||||
|
if (timeoutHandle) clearTimeout(timeoutHandle); // 清除超时
|
||||||
|
tcpClient.close();
|
||||||
|
resolve({
|
||||||
|
code: 2300028,
|
||||||
|
message: errMsg,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用 Promise.race 处理超时和 TCP 请求
|
||||||
|
Promise.race([timeoutPromise, new Promise<RES>((resolveMain) => {
|
||||||
|
// 将 resolve 逻辑移到此处
|
||||||
|
tcpClient.on('message', (data) => {
|
||||||
|
const res = handReceiveMessage(tcpClient, sendData, data.message);
|
||||||
|
if (res) {
|
||||||
|
resolveMain(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tcpClient.on('error', (e) => {
|
||||||
|
const errMsg = 'tcp client receive error' + JSON.stringify(e);
|
||||||
|
resolveMain({
|
||||||
|
code: 2300028,
|
||||||
|
message: errMsg,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})])
|
||||||
|
.then((result) => {
|
||||||
|
if (timeoutHandle) clearTimeout(timeoutHandle); // 清除超时
|
||||||
|
tcpClient.close();
|
||||||
|
resolve(result);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (timeoutHandle) clearTimeout(timeoutHandle); // 清除超时
|
||||||
|
tcpClient.close();
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//处理发送的数据
|
||||||
|
function handSendMessage(client: socket.TCPSocket, type, data) {
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
//开始考试 过程照片 考试结束需要分包
|
||||||
|
case '02-21-000009':
|
||||||
|
case '02-21-000012':
|
||||||
|
case '02-21-000014':
|
||||||
|
data.forEach((item, index) => {
|
||||||
|
console.log(TAG, "分包", index.toString(), JSON.stringify(item))
|
||||||
|
client.send({ data: new Uint8Array(item).buffer })
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case '02-21-000010':
|
||||||
|
case '02-21-000011':
|
||||||
|
case '02-21-000013':
|
||||||
|
client.send({ data: new Uint8Array(data).buffer })
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//处理接收的数据
|
||||||
|
function handReceiveMessage(client: socket.TCPSocket, sendData, rData: ArrayBuffer): RES {
|
||||||
|
const receiveData = new Uint8Array(rData)
|
||||||
|
console.info(TAG, 'receiveData=>' + JSON.stringify(receiveData))
|
||||||
|
//返回的消息类型
|
||||||
|
const messageType = receiveData[1];
|
||||||
|
console.info(TAG, 'receiveData messageType=>' + JSON.stringify(receiveData))
|
||||||
|
|
||||||
|
//流水号
|
||||||
|
const lsh = bytesToDecimal([receiveData[2], receiveData[3]]);
|
||||||
|
|
||||||
|
//开始补包
|
||||||
|
if (messageType === 0xF0) {
|
||||||
|
//获取消息体长度
|
||||||
|
const messageLength = receiveData[13]
|
||||||
|
//分包总数
|
||||||
|
const packages = receiveData.slice(14, 14 + messageLength * 2);
|
||||||
|
const forArr = new Array(messageLength).fill(1)
|
||||||
|
|
||||||
|
forArr.forEach((item, index) => {
|
||||||
|
const start = index * 2;
|
||||||
|
const end = start + 1;
|
||||||
|
const packageIndex = bytesToDecimal([packages[start], packages[end]]);
|
||||||
|
console.info(TAG, '补包内容' + JSON.stringify(new Uint8Array(sendData[packageIndex -1])))
|
||||||
|
printInBatches(new Uint8Array(sendData[packageIndex -1]), 100)
|
||||||
|
client.send({ data: new Uint8Array(sendData[packageIndex -1]).buffer });
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const decoder = util.TextDecoder.create('utf-8');
|
||||||
|
const messageLength = bytesToDecimal([receiveData[9], receiveData[10]]);
|
||||||
|
const markLength = receiveData[11];
|
||||||
|
const markContent = decoder.decodeWithStream(receiveData.slice(12, 12 + markLength));
|
||||||
|
console.info(TAG + messageType, 'markContent=>' + markContent)
|
||||||
|
const tipLength = receiveData[13];
|
||||||
|
const messageContent = decoder.decodeWithStream(receiveData.slice(13 + markLength, 13 + markLength + tipLength));
|
||||||
|
console.info(TAG + messageType, 'messageContent=>' + messageContent)
|
||||||
|
return {
|
||||||
|
code: markContent,
|
||||||
|
message: messageContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function printInBatches(array, batchSize) {
|
||||||
|
for (let i = 0; i < array.length; i += batchSize) {
|
||||||
|
const batch = array.slice(i, i + batchSize);
|
||||||
|
console.log(TAG, "补包细分", batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
125
entry/src/main/ets/tcp2byte/testData/testData.js
Normal file
125
entry/src/main/ets/tcp2byte/testData/testData.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
const test17C51 = {
|
||||||
|
wglb: "700204",
|
||||||
|
jkxlh: "370170020500013133",
|
||||||
|
glbm: "370100000400",
|
||||||
|
jgbh: "37010034",
|
||||||
|
sjbs: "02-21-000010",
|
||||||
|
data: {
|
||||||
|
sjbs: "02-21-000010",
|
||||||
|
param: {
|
||||||
|
sfzmhm: "684363640692131968",
|
||||||
|
kskm: "3",
|
||||||
|
ksxl: "3700198502",
|
||||||
|
kchp: "鲁A25UU1",
|
||||||
|
kssj: "2025-02-25 19:31:55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
file: { sjbs: "02-21-000010", param: [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const test17C52 = {
|
||||||
|
"wglb": "700204",
|
||||||
|
"jkxlh": "370170020500013133",
|
||||||
|
"glbm": "370100000400",
|
||||||
|
"jgbh": "37010034",
|
||||||
|
"sjbs": "02-21-000010",
|
||||||
|
"data": {
|
||||||
|
"sjbs": "02-21-000010",
|
||||||
|
"param": {
|
||||||
|
"sfzmhm": "211421199203200614",
|
||||||
|
"kskm": "3",
|
||||||
|
"ksxm": "40100",
|
||||||
|
"ksxl": "3700198504",
|
||||||
|
"kchp": "鲁A00YM8",
|
||||||
|
"kssj": "2025-01-06 13:59:08"
|
||||||
|
} },
|
||||||
|
"file": { "sjbs": "02-21-000010", "param": [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const test17C53 = {
|
||||||
|
"wglb": "700204",
|
||||||
|
"jkxlh": "370170020500013133",
|
||||||
|
"glbm": "370100000400",
|
||||||
|
"jgbh": "37010034",
|
||||||
|
"sjbs": "02-21-000011",
|
||||||
|
"data": {
|
||||||
|
"sjbs": "02-21-000011",
|
||||||
|
"param": {
|
||||||
|
"kffs": 1,
|
||||||
|
"kfsj": "2025-02-26 16:40:21",
|
||||||
|
"kfxm": "30123",
|
||||||
|
"kfxmmx": "2,43",
|
||||||
|
"kskm": "3",
|
||||||
|
"ksxm": "40200",
|
||||||
|
"sfzmhm": "137457799873815456"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"file": { "sjbs": "02-21-000011", "param": [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const test17C54 = {
|
||||||
|
"wglb": "700204",
|
||||||
|
"jkxlh": "370170020500013133",
|
||||||
|
"glbm": "370100000400",
|
||||||
|
"jgbh": "37010034",
|
||||||
|
"sjbs": "02-21-000012",
|
||||||
|
"data": {
|
||||||
|
"sjbs": "02-21-000012",
|
||||||
|
"param": {
|
||||||
|
"cs": 0,
|
||||||
|
"kskm": "3",
|
||||||
|
"ksxm": "40200",
|
||||||
|
"sfzmhm": "137457799873815456",
|
||||||
|
"zpsj": "2025-02-26 16:39:52"
|
||||||
|
} },
|
||||||
|
"file": { "sjbs": "02-21-000012", "param": [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const test17C55 = {
|
||||||
|
"wglb": "700204",
|
||||||
|
"jkxlh": "370170020500013133",
|
||||||
|
"glbm": "370100000400",
|
||||||
|
"jgbh": "37010034",
|
||||||
|
"sjbs": "02-21-000013",
|
||||||
|
"data": {
|
||||||
|
"param": {
|
||||||
|
"czlx": "1",
|
||||||
|
"jssj": "2025-01-06 13:59:11",
|
||||||
|
"kskm": "3",
|
||||||
|
"ksxl": "3700198504",
|
||||||
|
"ksxm": "40100",
|
||||||
|
"sfzmhm": "211421199203200614"
|
||||||
|
},
|
||||||
|
"sjbs": "02-21-000013"
|
||||||
|
},
|
||||||
|
"file": { "sjbs": "02-21-000013", "param": [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const test17C56 = {
|
||||||
|
"wglb": "700204",
|
||||||
|
"jkxlh": "370170020500013133",
|
||||||
|
"glbm": "370100000400",
|
||||||
|
"jgbh": "37010034",
|
||||||
|
"sjbs": "02-21-000014",
|
||||||
|
"data": {
|
||||||
|
"sjbs": "02-21-000014",
|
||||||
|
"param": {
|
||||||
|
"dwlc": "1,61;2,313;3,1223;4,1579;5,0",
|
||||||
|
"ghks": "0",
|
||||||
|
"jssj": "2025-01-06 14:08:04",
|
||||||
|
"kscj": 90,
|
||||||
|
"kskm": "3",
|
||||||
|
"kslc": 3193,
|
||||||
|
"sfzmhm": "211421199203200614"
|
||||||
|
} },
|
||||||
|
"file": { "sjbs": "02-21-000014", "param": [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
test17C51,
|
||||||
|
test17C52,
|
||||||
|
test17C53,
|
||||||
|
test17C54,
|
||||||
|
test17C55,
|
||||||
|
test17C56,
|
||||||
|
}
|
||||||
273
entry/src/main/ets/tcp2byte/testData/消息结构.pdf
Normal file
273
entry/src/main/ets/tcp2byte/testData/消息结构.pdf
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
A.1.1 消息结构
|
||||||
|
每条消息由标识位、消息头、消息体和校验码组成。
|
||||||
|
|
||||||
|
标识位 消息头 消息体 标识位
|
||||||
|
|
||||||
|
A.1.1.1 标识位
|
||||||
|
|
||||||
|
采用Ox7e表示,若校验码、消息头以及消息体中出现0x7e,则要进行转义处理,转义规
|
||||||
|
则定义如下:
|
||||||
|
|
||||||
|
0x7e<——>0x7d后紧跟一个0x02;
|
||||||
|
0x7d<——>0x7d后紧跟一个0x01。
|
||||||
|
转义处理过程如下:
|
||||||
|
发送消息时:消息封装——>转义;
|
||||||
|
接收消息时:转义还原——>解析消息。
|
||||||
|
示例:
|
||||||
|
发送一包内容为0x30 0x7e 0x08 0x7d 0x55的数据包,则经过封装如下:0x7e 0x30 7d 0x02
|
||||||
|
0x08 0x7d 0x01 0x55 0x7e。
|
||||||
|
|
||||||
|
A.1.1.2 消息头
|
||||||
|
|
||||||
|
消息头内容
|
||||||
|
|
||||||
|
一对请求和应答会使用相同的消息流水号。有分包时分包消息通知的流水号与请求一致。
|
||||||
|
|
||||||
|
起始字 字段 数据类型 描述及要求
|
||||||
|
节
|
||||||
|
消息类型
|
||||||
|
消息流水号 BYTE 对应不同业务,具体见消息体。
|
||||||
|
消息体长度 WORD 0-65535。用于并发是匹配应答
|
||||||
|
是否有分包 WORD 0-65535
|
||||||
|
分包总数 BYTE 0=无分包;1=有分包
|
||||||
|
分包序号 WORD 无分包时无此字段
|
||||||
|
WORD 无分包时无此字段。序号从 01 开始。
|
||||||
|
|
||||||
|
A.1.1.3 分包
|
||||||
|
|
||||||
|
当消息体长度超过 900 字节时,需启用分包对消息体进行拆分。
|
||||||
|
同一个请求的多个分包需要使用相同的消息流水号,并按照顺序从 01 开始依次提供序
|
||||||
|
号。
|
||||||
|
当接收到全部分包后,服务器会发送消息类型 0xF0 通知接收完全。
|
||||||
|
当某个消息流水号的分包未接收完全,且 5 秒内没有接收到新的分包,则会发送消息类
|
||||||
|
型消息类型 0xF0 通知需补发的分包序号。
|
||||||
|
当某个消息流水号的分包最后一次接收分包的时间点超过当前时间 10 分钟,该流水号
|
||||||
|
的分包内容将会被舍弃。该流水号将会可以重新用于新分包消息。
|
||||||
|
|
||||||
|
A.1.2 消息体
|
||||||
|
由head参数体、data参数体和files参数体组成。
|
||||||
|
|
||||||
|
head 参数体 data 参数体 files 参数体
|
||||||
|
|
||||||
|
A.1.2.1 head参数体
|
||||||
|
|
||||||
|
head参数体。请求需包含head参数体内容,应答head参数体为空,此时head参数体总长
|
||||||
|
度为0,没有后续字段内容。
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
head参数体总长度 WORD
|
||||||
|
wglb长度 BYTE 0-65535
|
||||||
|
wglb ASCII 0-255
|
||||||
|
jkxlh长度 BYTE 0-255
|
||||||
|
jkxlh ASCII 0-255
|
||||||
|
glbm长度 BYTE 0-255
|
||||||
|
glbm ASCII 0-255
|
||||||
|
jgbh长度 BYTE
|
||||||
|
jgbh ASCII
|
||||||
|
sjbs长度 BYTE
|
||||||
|
sjbs ASCII
|
||||||
|
|
||||||
|
A.1.2.2 data参数体和files参数体
|
||||||
|
当files参数体不存在时,仅保留file参数体总长度字段,值为0
|
||||||
|
|
||||||
|
A.1.2.2.1 消息0x01 02-21-000009-考试开始(17C51)
|
||||||
|
|
||||||
|
请求data参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
考生身份证明号码长度 BYTE 0-65535
|
||||||
|
考生身份证明号码 ASCII 0-255
|
||||||
|
考车号牌长度 BYTE
|
||||||
|
考车号牌 SRTING 0-255
|
||||||
|
考试科目 BYTE
|
||||||
|
考试路线长度 BYTE 2:科目二,3:科目三
|
||||||
|
考试路线 SRTING 0-255.为空时长度填 0。
|
||||||
|
开始时间 BCD(7) 为空时没有内容。跳过字段
|
||||||
|
yyyyMMddHHmmss
|
||||||
|
|
||||||
|
请求files参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
file参数体总长度 DWORD 0-4228250625
|
||||||
|
照片类型长度 BYTE 0-255
|
||||||
|
照片类型 ASCII
|
||||||
|
文件长度 DWORD 0-4228250625
|
||||||
|
文件 BYTE[n] 照片文件本身,无需编码
|
||||||
|
|
||||||
|
应答data参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
标记长度 BYTE 0-65535
|
||||||
|
标记 ASCII 0-255
|
||||||
|
提示信息长度 BYTE
|
||||||
|
提示信息 SRTING 0-255
|
||||||
|
考试项目长度 BYTE
|
||||||
|
考试项目 SRTING 0-255.
|
||||||
|
|
||||||
|
A.1.2.2.2 消息0x02 02-21-000010-考试项目开始(17C52)
|
||||||
|
|
||||||
|
请求 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
身份证明号码长度 BYTE 0-65535
|
||||||
|
身份证明号码 ASCII 0-255
|
||||||
|
考试科目 BYTE
|
||||||
|
考试项目 WORD 2:科目二,3:科目三
|
||||||
|
设备编号长度 BYTE
|
||||||
|
设备编号 ASCII yyyyMMddHHmmss
|
||||||
|
考试路线长度 BYTE
|
||||||
|
考试路线 ASCII
|
||||||
|
考车号牌长度 BYTE
|
||||||
|
考车号牌 STRING
|
||||||
|
开始时间 BCD(7)
|
||||||
|
|
||||||
|
应答 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
标记长度 BYTE 0-65535
|
||||||
|
标记 ASCII 0-255
|
||||||
|
提示信息长度 BYTE
|
||||||
|
提示信息 SRTING 0-255
|
||||||
|
A.1.2.2.3 消息0x03 02-21-000011-考试扣分(17C53)
|
||||||
|
|
||||||
|
请求 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
身份证明号码长度 BYTE 0-65535
|
||||||
|
身份证明号码 ASCII 0-255
|
||||||
|
考试科目 BYTE
|
||||||
|
考试项目长度 BYTE 2:科目二,3:科目三
|
||||||
|
考试项目 ASCII 0-255.
|
||||||
|
扣分项目长度 BYTE
|
||||||
|
扣分项目 ASCII yyyyMMddHHmmss
|
||||||
|
扣分时间 BCD(7) 1:系统扣分,2:人工扣分
|
||||||
|
扣分方式 BYTE
|
||||||
|
|
||||||
|
应答 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
标记长度 BYTE 0-65535
|
||||||
|
标记 ASCII 0-255
|
||||||
|
提示信息长度 BYTE
|
||||||
|
提示信息 SRTING 0-255
|
||||||
|
|
||||||
|
A.1.2.2.4 消息0x04 02-21-000012-考试过程图片(17C54)
|
||||||
|
|
||||||
|
请求 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
身份证明号码长度 BYTE 0-65535
|
||||||
|
身份证明号码 ASCII 0-255
|
||||||
|
考试科目 BYTE
|
||||||
|
考试项目长度 BYTE 2:科目二,3:科目三
|
||||||
|
考试项目 ASCII 0-255.
|
||||||
|
抓拍时间 BCD(7)
|
||||||
|
车速 BYTE yyyyMMddHHmmss
|
||||||
|
0-255.单位:km/H
|
||||||
|
|
||||||
|
请求 files 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
file参数体总长度 DWORD 0-4228250625
|
||||||
|
照片类型长度 BYTE 0-255
|
||||||
|
照片类型 ASCII 0-4228250625
|
||||||
|
文件长度 DWORD 照片文件本身,无需编码
|
||||||
|
文件 BYTE[n]
|
||||||
|
|
||||||
|
应答 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
标记长度 BYTE 0-65535
|
||||||
|
标记 ASCII 0-255
|
||||||
|
提示信息长度 BYTE
|
||||||
|
提示信息 SRTING 0-255
|
||||||
|
|
||||||
|
A.1.2.2.5 消息0x05 02-21-000013-考试项目结束(17C55)
|
||||||
|
|
||||||
|
请求 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
身份证明号码长度 BYTE 0-65535
|
||||||
|
身份证明号码 ASCII 0-255
|
||||||
|
考试科目 BYTE
|
||||||
|
考试项目长度 BYTE 2:科目二,3:科目三
|
||||||
|
考试项目 SRTING 0-255.
|
||||||
|
设备编号长度 BYTE
|
||||||
|
设备编号 ASCII yyyyMMddHHmmss
|
||||||
|
考试路线长度 BYTE 1:正常,0:撤销该考试项目记录
|
||||||
|
考试路线 ASCII
|
||||||
|
考车号牌长度 BYTE
|
||||||
|
考车号牌 STRING
|
||||||
|
结束时间 BCD(7)
|
||||||
|
操作类型 BYTE
|
||||||
|
|
||||||
|
应答 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
标记长度 BYTE 0-65535
|
||||||
|
标记 ASCII 0-255
|
||||||
|
提示信息长度 BYTE
|
||||||
|
提示信息 SRTING 0-255
|
||||||
|
|
||||||
|
A.1.2.2.6 消息0x06 02-21-000014-考试科目考试结束(17C56)
|
||||||
|
请求 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
身份证明号码长度 BYTE 0-65535
|
||||||
|
身份证明号码 ASCII 0-255
|
||||||
|
考试科目 BYTE
|
||||||
|
结束时间 BCD(7) 2:科目二,3:科目三
|
||||||
|
考试成绩 BYTE yyyyMMddHHmmss
|
||||||
|
是否更换考生 ASCII 0-100.
|
||||||
|
档位里程长度 BYTE 0:不更换,1:更换。
|
||||||
|
档位里程 ASCII
|
||||||
|
考试里程 WORD
|
||||||
|
|
||||||
|
请求 files 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
0-4228250625
|
||||||
|
file参数体总长度 DWORD
|
||||||
|
0-255
|
||||||
|
照片类型长度 BYTE
|
||||||
|
照片类型 ASCII 0-4228250625
|
||||||
|
文件长度 DWORD 照片文件本身,无需编码
|
||||||
|
文件 BYTE[n]
|
||||||
|
|
||||||
|
应答 data 参数体结构
|
||||||
|
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
标记长度 BYTE 0-65535
|
||||||
|
标记 ASCII 0-255
|
||||||
|
提示信息长度 BYTE
|
||||||
|
提示信息 SRTING 0-255
|
||||||
|
|
||||||
|
A.1.2.2.7 消息0XF0 分包接收状态通知
|
||||||
|
|
||||||
|
该消息由后台发送给设备。
|
||||||
|
当后台收到某个消息请求的报文头中存在分包信息,则必定会回复此应答。
|
||||||
|
当接收到某个消息的全部分包后,会立刻回复此应答。当最后一次接收到某个消息的分
|
||||||
|
包超过一定时间,则会发送该消息要求重新上传缺失分包。
|
||||||
|
|
||||||
|
请求 data 参数体结构
|
||||||
|
起始字节 字段 数据类型 描述及要求
|
||||||
|
data参数体总长度 WORD
|
||||||
|
需补消息流水号 0-65535
|
||||||
|
需补分包数
|
||||||
|
需补分包序号1 BYTE
|
||||||
|
需补分包序号 2 WORD
|
||||||
|
…… WORD
|
||||||
|
WORD
|
||||||
|
|
||||||
2
entry/src/main/ets/tcp2byte/utils/base64.js
Normal file
2
entry/src/main/ets/tcp2byte/utils/base64.js
Normal file
File diff suppressed because one or more lines are too long
501
entry/src/main/ets/tcp2byte/utils/tcp2byte.ts
Normal file
501
entry/src/main/ets/tcp2byte/utils/tcp2byte.ts
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
import { string2Bytes, str2UTF8, timeTOBCD } from './tools'
|
||||||
|
import Buffer from '@ohos.buffer'
|
||||||
|
import photo from './base64'
|
||||||
|
const TAG = '[TCP2BYTE]'
|
||||||
|
|
||||||
|
export default class TcpToByte {
|
||||||
|
//WORD 流水号
|
||||||
|
lsh = ''
|
||||||
|
//标识位
|
||||||
|
prefix = 0x7e;
|
||||||
|
nPrefix = 0x7d
|
||||||
|
//分包大小配置
|
||||||
|
packageSize = 900
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
getRequest(data){
|
||||||
|
const sjbs = data.sjbs
|
||||||
|
switch (sjbs){
|
||||||
|
case '02-21-000009':
|
||||||
|
return this.get17C51(data)
|
||||||
|
case '02-21-000010':
|
||||||
|
return this.get17C52(data)
|
||||||
|
case '02-21-000011':
|
||||||
|
return this.get17C53(data)
|
||||||
|
case '02-21-000012':
|
||||||
|
return this.get17C54(data)
|
||||||
|
case '02-21-000013':
|
||||||
|
return this.get17C55(data)
|
||||||
|
case '02-21-000014':
|
||||||
|
return this.get17C56(data)
|
||||||
|
|
||||||
|
default: return []
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取消息头
|
||||||
|
getHead(type, message) {
|
||||||
|
const lsh = this.getRandomLsh()
|
||||||
|
console.log('lsh', lsh)
|
||||||
|
return [type]
|
||||||
|
.concat(string2Bytes(lsh, 16))
|
||||||
|
.concat(string2Bytes(message.length, 16))//TODO 是否有分包
|
||||||
|
.concat([0])
|
||||||
|
//TODO 分包总数
|
||||||
|
//TODO 分包序号
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取消息里的消息头
|
||||||
|
getMsgHead(headMsg) {
|
||||||
|
const wglb = str2UTF8(headMsg.wglb)
|
||||||
|
const jkxlh = str2UTF8(headMsg.jkxlh)
|
||||||
|
const glbm = str2UTF8(headMsg.glbm)
|
||||||
|
const jgbh = str2UTF8(headMsg.jgbh)
|
||||||
|
const sjbs = str2UTF8(headMsg.sjbs)
|
||||||
|
|
||||||
|
return this.comBMsg({
|
||||||
|
wglb: {
|
||||||
|
values: wglb, isNeedLen: true
|
||||||
|
},
|
||||||
|
jkxlh: {
|
||||||
|
values: jkxlh, isNeedLen: true
|
||||||
|
},
|
||||||
|
glbm: {
|
||||||
|
values: glbm, isNeedLen: true
|
||||||
|
},
|
||||||
|
jgbh: {
|
||||||
|
values: jgbh, isNeedLen: true
|
||||||
|
},
|
||||||
|
sjbs: {
|
||||||
|
values: sjbs, isNeedLen: true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 考试开始
|
||||||
|
get17C51(drvexam) {
|
||||||
|
const packageSize = this.packageSize;
|
||||||
|
const prefix = this.prefix;
|
||||||
|
const lsh = this.getRandomLsh();
|
||||||
|
const temp = drvexam.data.param;
|
||||||
|
//身份证号码
|
||||||
|
const sfzmhm = str2UTF8(temp.sfzmhm)
|
||||||
|
//考试科目
|
||||||
|
const kskm = temp.kskm * 1
|
||||||
|
//考试路线
|
||||||
|
const ksxl = str2UTF8(temp.ksxl)
|
||||||
|
//考车号码
|
||||||
|
const kchp = str2UTF8(temp.kchp)
|
||||||
|
const time = timeTOBCD(temp.kssj)
|
||||||
|
|
||||||
|
const msgHead = this.getMsgHead(drvexam)
|
||||||
|
// const msg = this.comMsg([sfzmhm, [kskm], ksxm, time, cs])
|
||||||
|
const msg = this.comBMsg({
|
||||||
|
sfzmhm: {
|
||||||
|
values: sfzmhm, isNeedLen: true
|
||||||
|
},
|
||||||
|
kchp: {
|
||||||
|
values: kchp, isNeedLen: true
|
||||||
|
},
|
||||||
|
kskm: {
|
||||||
|
values: [kskm], isNeedLen: false
|
||||||
|
},
|
||||||
|
ksxl: {
|
||||||
|
values: ksxl, isNeedLen: true
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
values: time, isNeedLen: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const file = this.getBytePhoto(drvexam.file.param[0].data);
|
||||||
|
//拼接消息
|
||||||
|
const message = msgHead.concat(msg).concat(file)
|
||||||
|
const translateMessage = message;
|
||||||
|
const emptyArr = new Array(Math.ceil(translateMessage.length / packageSize)).fill(1);
|
||||||
|
const packages = []
|
||||||
|
emptyArr.forEach((item, index) => {
|
||||||
|
const currentMessage = this.checkHasPrefix(translateMessage.slice(index * packageSize, (index + 1) * packageSize));
|
||||||
|
const currentPackage =
|
||||||
|
[prefix, 0x01]
|
||||||
|
.concat(string2Bytes(lsh, 16))
|
||||||
|
.concat(string2Bytes(currentMessage.length, 16))
|
||||||
|
.concat([1])
|
||||||
|
.concat(string2Bytes(emptyArr.length, 16))
|
||||||
|
.concat(string2Bytes(index + 1, 16))
|
||||||
|
|
||||||
|
.concat(currentMessage)
|
||||||
|
.concat(prefix);
|
||||||
|
|
||||||
|
packages.push(currentPackage)
|
||||||
|
|
||||||
|
})
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 项目开始
|
||||||
|
get17C52(drvexam) {
|
||||||
|
const temp = drvexam.data.param
|
||||||
|
const msgHead = this.getMsgHead(drvexam)
|
||||||
|
//身份证号码
|
||||||
|
const sfzmhm = str2UTF8(temp.sfzmhm)
|
||||||
|
//考试科目
|
||||||
|
const kskm = temp.kskm * 1
|
||||||
|
//考试项目
|
||||||
|
const ksxm = string2Bytes(temp.ksxm, 16);
|
||||||
|
|
||||||
|
//TODO 科目三设备编号为空
|
||||||
|
|
||||||
|
//考试路线
|
||||||
|
const ksxl = str2UTF8(temp.ksxl)
|
||||||
|
//考车号码
|
||||||
|
const kchp = str2UTF8(temp.kchp)
|
||||||
|
|
||||||
|
const time = timeTOBCD(temp.kssj)
|
||||||
|
|
||||||
|
//file内容为空
|
||||||
|
const msg = this.comBMsg({
|
||||||
|
sfzmhm: {
|
||||||
|
values: sfzmhm, isNeedLen: true
|
||||||
|
},
|
||||||
|
kskm: {
|
||||||
|
values: [kskm], isNeedLen: false
|
||||||
|
},
|
||||||
|
ksxm: {
|
||||||
|
values: ksxm, isNeedLen: false
|
||||||
|
},
|
||||||
|
sbbm: {
|
||||||
|
values: [], isNeedLen: true
|
||||||
|
},
|
||||||
|
ksxl: {
|
||||||
|
values: ksxl, isNeedLen: true
|
||||||
|
},
|
||||||
|
kchp: {
|
||||||
|
values: kchp, isNeedLen: true
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
values: time, isNeedLen: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const file = [0, 0, 0, 0, 0]
|
||||||
|
//拼接消息
|
||||||
|
const message = msgHead.concat(msg).concat(file)
|
||||||
|
const translateMessage = this.checkHasPrefix(message)
|
||||||
|
const head = this.getHead(0x02, translateMessage)
|
||||||
|
|
||||||
|
const data = [0x7e].concat(head).concat(translateMessage).concat([0x7e])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扣分
|
||||||
|
get17C53(drvexam) {
|
||||||
|
const msgHead = this.getMsgHead(drvexam)
|
||||||
|
const temp = drvexam.data.param;
|
||||||
|
|
||||||
|
//身份证号码
|
||||||
|
const sfzmhm = str2UTF8(temp.sfzmhm)
|
||||||
|
//考试科目
|
||||||
|
const kskm = temp.kskm * 1
|
||||||
|
//扣分方式
|
||||||
|
const kffs = temp.kffs * 1
|
||||||
|
//考试项目
|
||||||
|
const ksxm = string2Bytes(temp.ksxm, 16);
|
||||||
|
//扣分项目
|
||||||
|
const kfxm = string2Bytes(temp.kfxm, 16);
|
||||||
|
|
||||||
|
//扣分时间
|
||||||
|
const time = timeTOBCD(temp.kfsj)
|
||||||
|
//扣分项目明细
|
||||||
|
const kfxmmx = str2UTF8(temp.kfxmmx);
|
||||||
|
|
||||||
|
const msg = this.comBMsg({
|
||||||
|
sfzmhm: {
|
||||||
|
values: sfzmhm, isNeedLen: true
|
||||||
|
},
|
||||||
|
kskm: {
|
||||||
|
values: [kskm], isNeedLen: false
|
||||||
|
},
|
||||||
|
ksxm: {
|
||||||
|
values: ksxm, isNeedLen: false
|
||||||
|
},
|
||||||
|
kfxm: {
|
||||||
|
values: kfxm, isNeedLen: false
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
values: time, isNeedLen: false
|
||||||
|
},
|
||||||
|
kffs: {
|
||||||
|
values: [kffs], isNeedLen: false
|
||||||
|
},
|
||||||
|
kfxmmx: {
|
||||||
|
values: kfxmmx, isNeedLen: true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
//file内容为空
|
||||||
|
const file = [0, 0, 0, 0, 0]
|
||||||
|
const message = msgHead.concat(msg).concat(file)
|
||||||
|
const translateMessage = this.checkHasPrefix(message)
|
||||||
|
const head = this.getHead(0x03, translateMessage)
|
||||||
|
const data = [0x7e].concat(head).concat(translateMessage).concat([0x7e])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过程照片
|
||||||
|
get17C54(drvexam) {
|
||||||
|
|
||||||
|
const packageSize = this.packageSize;
|
||||||
|
const prefix = this.prefix;
|
||||||
|
const lsh = this.getRandomLsh();
|
||||||
|
const temp = drvexam.data.param;
|
||||||
|
//身份证号码
|
||||||
|
const sfzmhm = str2UTF8(temp.sfzmhm)
|
||||||
|
//考试科目
|
||||||
|
const kskm = temp.kskm * 1
|
||||||
|
//考试项目
|
||||||
|
const ksxm = string2Bytes(temp.ksxm, 16);
|
||||||
|
//车速
|
||||||
|
const cs = temp.cs * 1
|
||||||
|
|
||||||
|
const time = timeTOBCD(temp.zpsj);
|
||||||
|
const msgHead = this.getMsgHead(drvexam)
|
||||||
|
// const msg = this.comMsg([sfzmhm, [kskm], ksxm, time, cs])
|
||||||
|
const msg = this.comBMsg({
|
||||||
|
sfzmhm: {
|
||||||
|
values: sfzmhm, isNeedLen: true
|
||||||
|
},
|
||||||
|
kskm: {
|
||||||
|
values: [kskm], isNeedLen: false
|
||||||
|
},
|
||||||
|
ksxm: {
|
||||||
|
values: ksxm, isNeedLen: false
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
values: time, isNeedLen: false
|
||||||
|
},
|
||||||
|
cs: {
|
||||||
|
values: [cs], isNeedLen: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const file = this.getBytePhoto(drvexam.file.param[0].data);
|
||||||
|
//拼接消息
|
||||||
|
const message = msgHead.concat(msg).concat(file)
|
||||||
|
const translateMessage = message;
|
||||||
|
const emptyArr = new Array(Math.ceil(translateMessage.length / packageSize)).fill(1);
|
||||||
|
const packages = []
|
||||||
|
emptyArr.forEach((item, index) => {
|
||||||
|
const currentMessage = this.checkHasPrefix(translateMessage.slice(index * packageSize, (index + 1) * packageSize));
|
||||||
|
const currentPackage =
|
||||||
|
[prefix, 0x04]
|
||||||
|
.concat(string2Bytes(lsh, 16))
|
||||||
|
.concat(string2Bytes(currentMessage.length, 16))
|
||||||
|
.concat([1])
|
||||||
|
.concat(string2Bytes(emptyArr.length, 16))
|
||||||
|
.concat(string2Bytes(index + 1, 16))
|
||||||
|
.concat(currentMessage)
|
||||||
|
.concat(prefix);
|
||||||
|
packages.push(currentPackage)
|
||||||
|
|
||||||
|
})
|
||||||
|
return packages;
|
||||||
|
//进行拆包
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 项目结束
|
||||||
|
get17C55(drvexam) {
|
||||||
|
const msgHead = this.getMsgHead(drvexam)
|
||||||
|
const temp = drvexam.data.param;
|
||||||
|
//身份证号码
|
||||||
|
const sfzmhm = str2UTF8(temp.sfzmhm)
|
||||||
|
//考试科目
|
||||||
|
const kskm = temp.kskm * 1
|
||||||
|
//考试项目
|
||||||
|
const ksxm = string2Bytes(temp.ksxm, 16);
|
||||||
|
|
||||||
|
//TODO 科目三设备编号为空
|
||||||
|
|
||||||
|
//考试路线
|
||||||
|
const ksxl = str2UTF8(temp.ksxl)
|
||||||
|
//考车号码
|
||||||
|
// const kchp = str2UTF8(temp.kchp)
|
||||||
|
|
||||||
|
const time = timeTOBCD(temp.jssj)
|
||||||
|
|
||||||
|
const czlx = temp.czlx * 1;
|
||||||
|
|
||||||
|
const msg = this.comBMsg({
|
||||||
|
sfzmhm: {
|
||||||
|
values: sfzmhm, isNeedLen: true
|
||||||
|
},
|
||||||
|
kskm: {
|
||||||
|
values: [kskm], isNeedLen: false
|
||||||
|
},
|
||||||
|
ksxm: {
|
||||||
|
values: ksxm, isNeedLen: false
|
||||||
|
},
|
||||||
|
sbbh: {
|
||||||
|
values: [], isNeedLen: true
|
||||||
|
},
|
||||||
|
ksxl: {
|
||||||
|
values: ksxl, isNeedLen: true
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
values: time, isNeedLen: false
|
||||||
|
},
|
||||||
|
czlx: {
|
||||||
|
values: [czlx], isNeedLen: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
//file内容为空
|
||||||
|
const file = [0, 0, 0, 0, 0]
|
||||||
|
const message = msgHead.concat(msg).concat(file)
|
||||||
|
const translateMessage = this.checkHasPrefix(message)
|
||||||
|
const head = this.getHead(0x05, msgHead)
|
||||||
|
const data = [0x7e].concat(head).concat(translateMessage).concat([0x7e])
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// 考试结束
|
||||||
|
get17C56(drvexam) {
|
||||||
|
const packageSize = this.packageSize;
|
||||||
|
const prefix = this.prefix;
|
||||||
|
const lsh = this.getRandomLsh();
|
||||||
|
const temp = drvexam.data.param;
|
||||||
|
//身份证号码
|
||||||
|
const sfzmhm = str2UTF8(temp.sfzmhm)
|
||||||
|
//考试科目
|
||||||
|
const kskm = temp.kskm * 1
|
||||||
|
//结束时间
|
||||||
|
const time = timeTOBCD(temp.jssj);
|
||||||
|
//考试成绩
|
||||||
|
const kscj = temp.kscj * 1;
|
||||||
|
//是否是更换考生
|
||||||
|
const ghks = 0;
|
||||||
|
//档位里程
|
||||||
|
const dwlc = str2UTF8(temp.dwlc);
|
||||||
|
//考试里程
|
||||||
|
const kslc = string2Bytes(temp.kslc, 16);
|
||||||
|
const msgHead = this.getMsgHead(drvexam)
|
||||||
|
// const msg = this.comMsg([sfzmhm, [kskm], time, [kscj], [ghks],dwlc,kslc])
|
||||||
|
const msg = this.comBMsg({
|
||||||
|
sfzmhm: {
|
||||||
|
values: sfzmhm, isNeedLen: true
|
||||||
|
},
|
||||||
|
kskm: {
|
||||||
|
values: [kskm], isNeedLen: false
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
values: time, isNeedLen: false
|
||||||
|
},
|
||||||
|
kscj: {
|
||||||
|
values: [kscj], isNeedLen: false
|
||||||
|
},
|
||||||
|
ghks: {
|
||||||
|
values: [ghks], isNeedLen: false
|
||||||
|
},
|
||||||
|
dwlc: {
|
||||||
|
values: dwlc, isNeedLen: true
|
||||||
|
},
|
||||||
|
kslc: {
|
||||||
|
values: kslc, isNeedLen: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const file = this.getBytePhoto(drvexam.file.param[0].data);
|
||||||
|
//拼接消息
|
||||||
|
const message = msgHead.concat(msg).concat(file)
|
||||||
|
const translateMessage = message;
|
||||||
|
const emptyArr = new Array(Math.ceil(translateMessage.length / packageSize)).fill(1);
|
||||||
|
const packages = []
|
||||||
|
emptyArr.forEach((item, index) => {
|
||||||
|
const currentMessage = this.checkHasPrefix(translateMessage.slice(index * packageSize, (index + 1) * packageSize));
|
||||||
|
const currentPackage =
|
||||||
|
[prefix, 0x06]
|
||||||
|
.concat(string2Bytes(lsh, 16))
|
||||||
|
.concat(string2Bytes(currentMessage.length, 16))
|
||||||
|
.concat([1])
|
||||||
|
.concat(string2Bytes(emptyArr.length, 16))
|
||||||
|
.concat(string2Bytes(index + 1, 16))
|
||||||
|
.concat(currentMessage)
|
||||||
|
.concat(prefix);
|
||||||
|
packages.push(currentPackage)
|
||||||
|
|
||||||
|
})
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装msg
|
||||||
|
comBMsg(msg) {
|
||||||
|
const keys = Reflect.ownKeys(msg)
|
||||||
|
let temp = []
|
||||||
|
keys.forEach(msgKey => {
|
||||||
|
const currentMsg = msg[msgKey]
|
||||||
|
const {isNeedLen,values} = currentMsg;
|
||||||
|
if (isNeedLen) {
|
||||||
|
temp = temp.concat([values.length]).concat(values)
|
||||||
|
} else {
|
||||||
|
temp = temp.concat(values)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (string2Bytes(temp.length, 16)).concat(temp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片处理
|
||||||
|
getBytePhoto(base64) {
|
||||||
|
const buffer = Buffer.from(base64, 'base64');
|
||||||
|
let arr = []
|
||||||
|
for (let i = 0; i < buffer.length; i++) {
|
||||||
|
arr.push(buffer[i]);
|
||||||
|
}
|
||||||
|
return (string2Bytes(arr.length + 5, 4 * 8)).concat([0]).concat(string2Bytes(arr.length, 4 * 8)).concat(arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//随机获取流水号
|
||||||
|
getRandomLsh() {
|
||||||
|
return Math.floor(Math.random() * 65535);
|
||||||
|
}
|
||||||
|
|
||||||
|
//转换消息类型
|
||||||
|
getMessageType(id) {
|
||||||
|
switch (id) {
|
||||||
|
case '17C51':
|
||||||
|
return 0x01
|
||||||
|
case '17C52':
|
||||||
|
return 0x02
|
||||||
|
case '17C53':
|
||||||
|
return 0x03
|
||||||
|
case '17C54':
|
||||||
|
return 0x04
|
||||||
|
case '17C55':
|
||||||
|
return 0x05
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查字节中是否有标识头字段
|
||||||
|
checkHasPrefix(message) {
|
||||||
|
const {prefix,nPrefix} = this;
|
||||||
|
let preMessage = [];
|
||||||
|
|
||||||
|
message.forEach((i, index) => {
|
||||||
|
|
||||||
|
if (i === prefix) {
|
||||||
|
preMessage = preMessage.concat([0x7d, 2])
|
||||||
|
} else if (i === nPrefix) {
|
||||||
|
preMessage = preMessage.concat([0x7d, 1])
|
||||||
|
} else {
|
||||||
|
preMessage.push(i)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return preMessage
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
68
entry/src/main/ets/tcp2byte/utils/tools.ts
Normal file
68
entry/src/main/ets/tcp2byte/utils/tools.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import util from '@ohos.util'
|
||||||
|
//字符串转byte数组
|
||||||
|
export function string2Bytes(number, len) {
|
||||||
|
let str = (Math.floor(+number)).toString(2);
|
||||||
|
if (str.length > len) {
|
||||||
|
console.log('数据长度不对~~');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const byteString = fillZero(str, len);
|
||||||
|
|
||||||
|
const arrBytes = new Array();
|
||||||
|
for (let i = byteString.length; i > 0;) {
|
||||||
|
let j = i - 8;
|
||||||
|
if (j < 0) {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
let s = byteString.slice(j, i);
|
||||||
|
let v = parseInt(s, 2);
|
||||||
|
arrBytes.push(v);
|
||||||
|
i = i - 8
|
||||||
|
|
||||||
|
}
|
||||||
|
return arrBytes.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
//字符串转utf-8
|
||||||
|
export function str2UTF8(str) {
|
||||||
|
let encoder = new util.TextEncoder()
|
||||||
|
return Array.from(encoder.encodeInto(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
//时间转bcd格式
|
||||||
|
export function timeTOBCD(timeStr) {
|
||||||
|
const time = timeStr.split(' ')[0].split('-').join('') + timeStr.split(' ')[1].split(':').join('')
|
||||||
|
const year_one = parseInt(time.slice(0, 2), 16)
|
||||||
|
const year_two = parseInt(time.slice(2, 4), 16)
|
||||||
|
const month = parseInt(time.slice(4, 6), 16)
|
||||||
|
const day = parseInt(time.slice(6, 8), 16)
|
||||||
|
const hour = parseInt(time.slice(8, 10), 16)
|
||||||
|
const min = parseInt(time.slice(10, 12), 16)
|
||||||
|
const sec = parseInt(time.slice(12, 14), 16)
|
||||||
|
|
||||||
|
return [year_one,year_two,month, day, hour, min, sec]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fillZero(str, len) {
|
||||||
|
str = str + '';
|
||||||
|
if (str.length > len || !len) {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
let num = len - str.length;
|
||||||
|
let zeroStr = '';
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
zeroStr = zeroStr + '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
return zeroStr + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bytesToDecimal(bytes) {
|
||||||
|
let result = 0;
|
||||||
|
for (let i = 0; i < bytes.length; i++) {
|
||||||
|
result = (result << 8) + bytes[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"hvigorVersion": "3.0.9",
|
"hvigorVersion": "3.2.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ohos/hvigor-ohos-plugin": "3.0.9"
|
"@ohos/hvigor-ohos-plugin": "3.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,13 +1,15 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 2,
|
||||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||||
"specifiers": {
|
"specifiers": {
|
||||||
"@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6"
|
"@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6"
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ohos/hypium@1.0.6": {
|
"@ohos/hypium@1.0.6": {
|
||||||
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
|
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
|
||||||
"integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ=="
|
"integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ==",
|
||||||
|
"registryType": "ohpm",
|
||||||
|
"shasum": "3f5fed65372633233264b3447705b0831dfe7ea1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user