langjie-m-play 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/service/GtcServiceWebSocketImpl.d.ts +1 -0
- package/service/GtcServiceWebSocketImpl.js +27 -46
- package/service/MPlay.js +3 -1
- package/utils/DataGramUtil.d.ts +4 -0
- package/utils/DataGramUtil.js +8 -0
- package/utils/NPack.d.ts +53 -0
- package/utils/NPack.js +261 -0
- package/utils/RemoteBinData.d.ts +45 -0
- package/utils/RemoteBinData.js +180 -0
package/package.json
CHANGED
|
@@ -20,6 +20,7 @@ declare class GtcServiceWebSocketImpl implements IGtcService {
|
|
|
20
20
|
private m_isNormalClose;
|
|
21
21
|
constructor();
|
|
22
22
|
buffer2GramJson(buffer: Uint8Array): void;
|
|
23
|
+
buffer2EventJson(buffer: Uint8Array): void;
|
|
23
24
|
init(url: string, connectCallback: () => void, disconnectCallback: () => void): Promise<boolean>;
|
|
24
25
|
_initWebSocket(): Promise<boolean>;
|
|
25
26
|
_reconnect(): void;
|
|
@@ -14,8 +14,8 @@ import { PubSubUtil } from "../utils/PubSubUtil";
|
|
|
14
14
|
import { SubKeyEnum } from "../utils/enums/SubKeyEnum";
|
|
15
15
|
// @ts-ignore
|
|
16
16
|
import { MsgEventTypeEnum } from "../domain/enums/MsgEventTypeEnum";
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
17
|
+
import { RemoteDataGramList, RemoteEventPack, RemoteBinDataTypeEnum, RemoteBinDataType } from "../utils/RemoteBinData";
|
|
18
|
+
import { MixGramTypeEnum } from "../domain/enums/MixGramTypeEnum";
|
|
19
19
|
/**
|
|
20
20
|
* 远程gtc服务WebSocket实现
|
|
21
21
|
*/
|
|
@@ -36,51 +36,26 @@ class GtcServiceWebSocketImpl {
|
|
|
36
36
|
this.m_isNormalClose = false;
|
|
37
37
|
}
|
|
38
38
|
buffer2GramJson(buffer) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"method": null,
|
|
44
|
-
"result": {
|
|
45
|
-
"ctrlIndex": 0,
|
|
46
|
-
"data": {
|
|
47
|
-
"DataGramList": []
|
|
48
|
-
},
|
|
49
|
-
"msgEventType": 1,
|
|
50
|
-
"serviceType": 2
|
|
51
|
-
},
|
|
52
|
-
"slaveInstId": null,
|
|
53
|
-
"timestamp": 0
|
|
54
|
-
};
|
|
55
|
-
const tagLength = DataGramUtil.tagLength();
|
|
56
|
-
if (buffer.length % (tagLength * 4) != 0) {
|
|
57
|
-
console.error("length is err", tagLength, buffer.length);
|
|
39
|
+
const remoteDataGramList = RemoteDataGramList.Build(buffer);
|
|
40
|
+
const mixGramTypeEnum = remoteDataGramList.MixGramTypeType();
|
|
41
|
+
const retGramJson = remoteDataGramList.ToJson();
|
|
42
|
+
if (retGramJson == null) {
|
|
58
43
|
return;
|
|
59
44
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// 单个数据项的uint32数组(对应原line)
|
|
66
|
-
const singleLineItemList = [];
|
|
67
|
-
// 遍历当前数据项的所有标签,拼接4字节为uint32
|
|
68
|
-
for (let tagIdx = 0; tagIdx < tagLength; tagIdx++) {
|
|
69
|
-
// 计算当前标签在DataView中的字节偏移(行偏移 + 标签偏移×4字节)
|
|
70
|
-
const byteOffset = lineOffset + (tagIdx * 4);
|
|
71
|
-
const uint32Value = dataView.getUint32(byteOffset, true);
|
|
72
|
-
if (DataGramUtil.isDVB(tagIdx)) {
|
|
73
|
-
const strValue = Dvb.Dvb2String(uint32Value);
|
|
74
|
-
singleLineItemList.push(strValue);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
singleLineItemList.push(uint32Value.toString(10));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
dataGramList.push(singleLineItemList);
|
|
45
|
+
if (mixGramTypeEnum == MixGramTypeEnum.GRAM) {
|
|
46
|
+
this.dataGram(retGramJson);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
PubSubUtil.publish(JsonRpcEventEnum.MIX_DATAGRAM, retGramJson);
|
|
81
50
|
}
|
|
82
|
-
|
|
83
|
-
|
|
51
|
+
}
|
|
52
|
+
buffer2EventJson(buffer) {
|
|
53
|
+
const remoteEventPack = RemoteEventPack.Build(buffer);
|
|
54
|
+
const remoteEventJson = remoteEventPack.ToJson();
|
|
55
|
+
if (remoteEventJson == null) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
PubSubUtil.publish(JsonRpcEventEnum.MIX_DATAGRAM, remoteEventJson);
|
|
84
59
|
}
|
|
85
60
|
init(url, connectCallback, disconnectCallback) {
|
|
86
61
|
this.m_connectCallback = connectCallback;
|
|
@@ -118,8 +93,14 @@ class GtcServiceWebSocketImpl {
|
|
|
118
93
|
reader.onload = function (e) {
|
|
119
94
|
let arrayBuffer = e.target.result;
|
|
120
95
|
// @ts-ignore
|
|
121
|
-
let
|
|
122
|
-
|
|
96
|
+
let uint8Array = new Uint8Array(arrayBuffer);
|
|
97
|
+
const remoteBinDataTypeEnum = RemoteBinDataType(uint8Array);
|
|
98
|
+
if (remoteBinDataTypeEnum === RemoteBinDataTypeEnum.R_DATAGRAM_LIST) {
|
|
99
|
+
that.buffer2GramJson(uint8Array);
|
|
100
|
+
}
|
|
101
|
+
else if (remoteBinDataTypeEnum === RemoteBinDataTypeEnum.R_EVENT_PACK) {
|
|
102
|
+
that.buffer2EventJson(uint8Array);
|
|
103
|
+
}
|
|
123
104
|
};
|
|
124
105
|
reader.readAsArrayBuffer(blob);
|
|
125
106
|
return;
|
package/service/MPlay.js
CHANGED
|
@@ -482,7 +482,9 @@ export class MPlay {
|
|
|
482
482
|
subscribeActionGoGram(fn) {
|
|
483
483
|
return __awaiter(this, void 0, void 0, function* () {
|
|
484
484
|
this.actionGoGramCallBack = fn;
|
|
485
|
-
|
|
485
|
+
const result = yield GtcClient.subscribeActionGoGram(this.instId, this.serviceType, this.ctrlIndex);
|
|
486
|
+
DataGramUtil.registerMixGramTagMap(result);
|
|
487
|
+
return result;
|
|
486
488
|
});
|
|
487
489
|
}
|
|
488
490
|
}
|
package/utils/DataGramUtil.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import { MixGramTypeEnum } from "../domain/enums/MixGramTypeEnum";
|
|
1
2
|
export declare class DataGramUtil {
|
|
2
3
|
private static TAG_LIST;
|
|
3
4
|
private static FLAG_TAG_LIST;
|
|
5
|
+
private static FLAG_MIX_GRAM_TAG_MAP;
|
|
4
6
|
/**
|
|
5
7
|
* 注册订阅串
|
|
6
8
|
*
|
|
7
9
|
* @param tags 订阅串
|
|
8
10
|
*/
|
|
9
11
|
static registerTag(tags: string): void;
|
|
12
|
+
static registerMixGramTagMap(tagMap: Record<MixGramTypeEnum, Array<string>>): void;
|
|
10
13
|
/**
|
|
11
14
|
* 根据索引判断是否DVB码
|
|
12
15
|
*
|
|
@@ -14,4 +17,5 @@ export declare class DataGramUtil {
|
|
|
14
17
|
*/
|
|
15
18
|
static isDVB(index: number): boolean;
|
|
16
19
|
static tagLength(): number;
|
|
20
|
+
static mixGramTagMap(): Record<MixGramTypeEnum, Array<string>>;
|
|
17
21
|
}
|
package/utils/DataGramUtil.js
CHANGED
|
@@ -7,6 +7,9 @@ export class DataGramUtil {
|
|
|
7
7
|
static registerTag(tags) {
|
|
8
8
|
DataGramUtil.TAG_LIST = tags.split(',');
|
|
9
9
|
}
|
|
10
|
+
static registerMixGramTagMap(tagMap) {
|
|
11
|
+
DataGramUtil.FLAG_MIX_GRAM_TAG_MAP = tagMap;
|
|
12
|
+
}
|
|
10
13
|
/**
|
|
11
14
|
* 根据索引判断是否DVB码
|
|
12
15
|
*
|
|
@@ -15,6 +18,7 @@ export class DataGramUtil {
|
|
|
15
18
|
static isDVB(index) {
|
|
16
19
|
const tag = DataGramUtil.TAG_LIST[index];
|
|
17
20
|
for (let i = 0; i < DataGramUtil.FLAG_TAG_LIST.length; i++) {
|
|
21
|
+
// @ts-ignore
|
|
18
22
|
if (tag.endsWith(DataGramUtil.FLAG_TAG_LIST[i])) {
|
|
19
23
|
return false;
|
|
20
24
|
}
|
|
@@ -24,6 +28,10 @@ export class DataGramUtil {
|
|
|
24
28
|
static tagLength() {
|
|
25
29
|
return DataGramUtil.TAG_LIST.length;
|
|
26
30
|
}
|
|
31
|
+
static mixGramTagMap() {
|
|
32
|
+
return DataGramUtil.FLAG_MIX_GRAM_TAG_MAP;
|
|
33
|
+
}
|
|
27
34
|
}
|
|
28
35
|
DataGramUtil.TAG_LIST = [];
|
|
29
36
|
DataGramUtil.FLAG_TAG_LIST = ['Time', 'Event', 'Intent'];
|
|
37
|
+
DataGramUtil.FLAG_MIX_GRAM_TAG_MAP = null;
|
package/utils/NPack.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export declare enum NpackTypeEnum {
|
|
2
|
+
NULL_TYPE = 0,
|
|
3
|
+
W_TYPE = 1,
|
|
4
|
+
DVB_TYPE = 2,
|
|
5
|
+
DW_TYPE = 3,
|
|
6
|
+
INT64_TYPE = 4,
|
|
7
|
+
STR_TYPE = 16,
|
|
8
|
+
WA_TYPE = 17,
|
|
9
|
+
DVBA_TYPE = 18,
|
|
10
|
+
DWA_TYPE = 19,
|
|
11
|
+
KEY_TYPE = 20,
|
|
12
|
+
STRUCT_TYPE = 32,
|
|
13
|
+
STRUCTA_TYPE = 48,
|
|
14
|
+
PACK_TYPE = 64,
|
|
15
|
+
NULL_NID = 1536,
|
|
16
|
+
W_NID = 1537,
|
|
17
|
+
DVB_NID = 1538,
|
|
18
|
+
DW_NID = 1539,
|
|
19
|
+
INT64_NID = 1540,
|
|
20
|
+
STR_NID = 1552,
|
|
21
|
+
WA_NID = 1553,
|
|
22
|
+
DVBA_NID = 1554,
|
|
23
|
+
DWA_NID = 1555,
|
|
24
|
+
STRUCT_NID = 1568,
|
|
25
|
+
STRUCTA_NID = 1584,
|
|
26
|
+
PACK_NID = 1600,
|
|
27
|
+
OBJ_PACK = 1601,
|
|
28
|
+
UNIT_LIST = 2176
|
|
29
|
+
}
|
|
30
|
+
export declare class NPack {
|
|
31
|
+
m_buffer: Uint8Array;
|
|
32
|
+
m_dataview: DataView;
|
|
33
|
+
m_byteOffset: number;
|
|
34
|
+
constructor(buffer: Uint8Array, byteOffset: number);
|
|
35
|
+
HeadSize(): number;
|
|
36
|
+
Length(): number;
|
|
37
|
+
Type(): number;
|
|
38
|
+
NLENGTH(iterPtr: number): number;
|
|
39
|
+
static IS_NULL(t: number): boolean;
|
|
40
|
+
static IS_NUMBER(t: number): boolean;
|
|
41
|
+
static IS_ARRAY(t: number): boolean;
|
|
42
|
+
static IS_STRUCT(t: number): boolean;
|
|
43
|
+
static IS_BLOCK(t: number): boolean;
|
|
44
|
+
static IS_PACK(t: number): boolean;
|
|
45
|
+
static IS_LIST(t: number): boolean;
|
|
46
|
+
Count(): number;
|
|
47
|
+
GetMember(index: number): NPack | null;
|
|
48
|
+
private _parseNumber;
|
|
49
|
+
private _parseString;
|
|
50
|
+
ToRawJson(maxDepth?: number, visited?: WeakSet<NPack>): any;
|
|
51
|
+
ToJson(maxDepth?: number, visited?: WeakSet<NPack>): any;
|
|
52
|
+
static Build(buffer: Uint8Array, byteOffset: number): NPack;
|
|
53
|
+
}
|
package/utils/NPack.js
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import Dvb from "./Dvb";
|
|
2
|
+
// 枚举保持不变
|
|
3
|
+
export var NpackTypeEnum;
|
|
4
|
+
(function (NpackTypeEnum) {
|
|
5
|
+
NpackTypeEnum[NpackTypeEnum["NULL_TYPE"] = 0] = "NULL_TYPE";
|
|
6
|
+
NpackTypeEnum[NpackTypeEnum["W_TYPE"] = 1] = "W_TYPE";
|
|
7
|
+
NpackTypeEnum[NpackTypeEnum["DVB_TYPE"] = 2] = "DVB_TYPE";
|
|
8
|
+
NpackTypeEnum[NpackTypeEnum["DW_TYPE"] = 3] = "DW_TYPE";
|
|
9
|
+
NpackTypeEnum[NpackTypeEnum["INT64_TYPE"] = 4] = "INT64_TYPE";
|
|
10
|
+
NpackTypeEnum[NpackTypeEnum["STR_TYPE"] = 16] = "STR_TYPE";
|
|
11
|
+
NpackTypeEnum[NpackTypeEnum["WA_TYPE"] = 17] = "WA_TYPE";
|
|
12
|
+
NpackTypeEnum[NpackTypeEnum["DVBA_TYPE"] = 18] = "DVBA_TYPE";
|
|
13
|
+
NpackTypeEnum[NpackTypeEnum["DWA_TYPE"] = 19] = "DWA_TYPE";
|
|
14
|
+
NpackTypeEnum[NpackTypeEnum["KEY_TYPE"] = 20] = "KEY_TYPE";
|
|
15
|
+
NpackTypeEnum[NpackTypeEnum["STRUCT_TYPE"] = 32] = "STRUCT_TYPE";
|
|
16
|
+
NpackTypeEnum[NpackTypeEnum["STRUCTA_TYPE"] = 48] = "STRUCTA_TYPE";
|
|
17
|
+
NpackTypeEnum[NpackTypeEnum["PACK_TYPE"] = 64] = "PACK_TYPE";
|
|
18
|
+
NpackTypeEnum[NpackTypeEnum["NULL_NID"] = 1536] = "NULL_NID";
|
|
19
|
+
NpackTypeEnum[NpackTypeEnum["W_NID"] = 1537] = "W_NID";
|
|
20
|
+
NpackTypeEnum[NpackTypeEnum["DVB_NID"] = 1538] = "DVB_NID";
|
|
21
|
+
NpackTypeEnum[NpackTypeEnum["DW_NID"] = 1539] = "DW_NID";
|
|
22
|
+
NpackTypeEnum[NpackTypeEnum["INT64_NID"] = 1540] = "INT64_NID";
|
|
23
|
+
NpackTypeEnum[NpackTypeEnum["STR_NID"] = 1552] = "STR_NID";
|
|
24
|
+
NpackTypeEnum[NpackTypeEnum["WA_NID"] = 1553] = "WA_NID";
|
|
25
|
+
NpackTypeEnum[NpackTypeEnum["DVBA_NID"] = 1554] = "DVBA_NID";
|
|
26
|
+
NpackTypeEnum[NpackTypeEnum["DWA_NID"] = 1555] = "DWA_NID";
|
|
27
|
+
NpackTypeEnum[NpackTypeEnum["STRUCT_NID"] = 1568] = "STRUCT_NID";
|
|
28
|
+
NpackTypeEnum[NpackTypeEnum["STRUCTA_NID"] = 1584] = "STRUCTA_NID";
|
|
29
|
+
NpackTypeEnum[NpackTypeEnum["PACK_NID"] = 1600] = "PACK_NID";
|
|
30
|
+
NpackTypeEnum[NpackTypeEnum["OBJ_PACK"] = 1601] = "OBJ_PACK";
|
|
31
|
+
NpackTypeEnum[NpackTypeEnum["UNIT_LIST"] = 2176] = "UNIT_LIST";
|
|
32
|
+
})(NpackTypeEnum || (NpackTypeEnum = {}));
|
|
33
|
+
export class NPack {
|
|
34
|
+
constructor(buffer, byteOffset) {
|
|
35
|
+
if (!buffer || buffer.byteLength === 0) {
|
|
36
|
+
throw new Error("NPack buffer is empty or null");
|
|
37
|
+
}
|
|
38
|
+
if (byteOffset < 0 || byteOffset > buffer.byteLength) {
|
|
39
|
+
throw new RangeError(`byteOffset ${byteOffset} out of range [0, ${buffer.byteLength}]`);
|
|
40
|
+
}
|
|
41
|
+
this.m_buffer = buffer;
|
|
42
|
+
this.m_byteOffset = byteOffset;
|
|
43
|
+
const realOffset = buffer.byteOffset + byteOffset;
|
|
44
|
+
const realLength = Math.max(0, buffer.byteLength - byteOffset);
|
|
45
|
+
this.m_dataview = new DataView(buffer.buffer, realOffset, realLength);
|
|
46
|
+
}
|
|
47
|
+
HeadSize() {
|
|
48
|
+
if (this.m_dataview.byteLength <= 4) {
|
|
49
|
+
return 4;
|
|
50
|
+
}
|
|
51
|
+
const ntype = this.Type();
|
|
52
|
+
const headSize = (ntype >> 8);
|
|
53
|
+
return headSize === 0 ? 4 : headSize;
|
|
54
|
+
}
|
|
55
|
+
Length() {
|
|
56
|
+
if (this.m_dataview.byteLength < 2) {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
return this.m_dataview.getUint16(0, true);
|
|
60
|
+
}
|
|
61
|
+
Type() {
|
|
62
|
+
if (this.m_dataview.byteLength < 4) {
|
|
63
|
+
return NpackTypeEnum.NULL_TYPE;
|
|
64
|
+
}
|
|
65
|
+
return this.m_dataview.getUint16(2, true);
|
|
66
|
+
}
|
|
67
|
+
NLENGTH(iterPtr) {
|
|
68
|
+
if (iterPtr < 0 || iterPtr + 2 > this.m_dataview.byteLength) {
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
return this.m_dataview.getUint16(iterPtr, true);
|
|
72
|
+
}
|
|
73
|
+
static IS_NULL(t) {
|
|
74
|
+
return (t & 0x00FF) === NpackTypeEnum.NULL_TYPE;
|
|
75
|
+
}
|
|
76
|
+
static IS_NUMBER(t) {
|
|
77
|
+
return (t & 0x00F0) === 0 && !this.IS_NULL(t);
|
|
78
|
+
}
|
|
79
|
+
static IS_ARRAY(t) {
|
|
80
|
+
return (t & 0x0010) > 0;
|
|
81
|
+
}
|
|
82
|
+
static IS_STRUCT(t) {
|
|
83
|
+
return (t & 0x0020) > 0;
|
|
84
|
+
}
|
|
85
|
+
static IS_BLOCK(t) {
|
|
86
|
+
return (t & 0x0030) > 0;
|
|
87
|
+
}
|
|
88
|
+
static IS_PACK(t) {
|
|
89
|
+
return (t & 0x0040) > 0;
|
|
90
|
+
}
|
|
91
|
+
static IS_LIST(t) {
|
|
92
|
+
return (t & 0x0080) > 0;
|
|
93
|
+
}
|
|
94
|
+
Count() {
|
|
95
|
+
const totalLength = this.Length();
|
|
96
|
+
const headSize = this.HeadSize();
|
|
97
|
+
if (totalLength <= headSize || this.m_dataview.byteLength < totalLength) {
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
let sumLength = headSize;
|
|
101
|
+
let count = 0;
|
|
102
|
+
let iterPtr = headSize;
|
|
103
|
+
let iterLen = this.NLENGTH(iterPtr);
|
|
104
|
+
while (sumLength < totalLength) {
|
|
105
|
+
if (iterLen <= 0 || iterPtr + iterLen > totalLength) {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
count++;
|
|
109
|
+
sumLength += iterLen;
|
|
110
|
+
iterPtr += iterLen;
|
|
111
|
+
iterLen = this.NLENGTH(iterPtr);
|
|
112
|
+
}
|
|
113
|
+
return count;
|
|
114
|
+
}
|
|
115
|
+
GetMember(index) {
|
|
116
|
+
if (index < 0)
|
|
117
|
+
return null;
|
|
118
|
+
const totalLength = this.Length();
|
|
119
|
+
const headSize = this.HeadSize();
|
|
120
|
+
if (totalLength <= headSize || this.m_dataview.byteLength < totalLength) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
let sumLength = headSize;
|
|
124
|
+
let count = 0;
|
|
125
|
+
let iterPtr = headSize;
|
|
126
|
+
let iterLen = this.NLENGTH(iterPtr);
|
|
127
|
+
while (count < index) {
|
|
128
|
+
if (iterLen <= 0 || iterPtr + iterLen > totalLength) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
count++;
|
|
132
|
+
sumLength += iterLen;
|
|
133
|
+
if (sumLength >= totalLength) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
iterPtr += iterLen;
|
|
137
|
+
iterLen = this.NLENGTH(iterPtr);
|
|
138
|
+
}
|
|
139
|
+
const newOffset = this.m_byteOffset + iterPtr;
|
|
140
|
+
if (newOffset >= this.m_buffer.byteLength) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
return NPack.Build(this.m_buffer, newOffset);
|
|
144
|
+
}
|
|
145
|
+
_parseNumber(type) {
|
|
146
|
+
switch (type) {
|
|
147
|
+
case NpackTypeEnum.W_TYPE:
|
|
148
|
+
return this.m_dataview.byteLength >= 4 ? this.m_dataview.getUint16(4, true) : null;
|
|
149
|
+
case NpackTypeEnum.DVB_TYPE:
|
|
150
|
+
return Dvb.Dvb2String(this.m_dataview.getUint32(4, true));
|
|
151
|
+
case NpackTypeEnum.DW_TYPE:
|
|
152
|
+
return this.m_dataview.byteLength >= 8 ? this.m_dataview.getUint32(4, true) : null;
|
|
153
|
+
case NpackTypeEnum.INT64_TYPE:
|
|
154
|
+
return this.m_dataview.byteLength >= 12 ? this.m_dataview.getUint32(4, true) : null;
|
|
155
|
+
default:
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
_parseString() {
|
|
160
|
+
const strLen = this.Length() - 4; // 假设字符串长度在偏移4处
|
|
161
|
+
if (strLen <= 0 || 4 + strLen > this.m_dataview.byteLength) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
const uint8Arr = new Uint8Array(this.m_dataview.buffer, this.m_dataview.byteOffset + 4, strLen);
|
|
165
|
+
let nullIndex = uint8Arr.findIndex(byte => byte === 0);
|
|
166
|
+
// 若未找到空字符,取完整长度;否则取空字符前的有效长度
|
|
167
|
+
const validLength = nullIndex === -1 ? strLen : nullIndex;
|
|
168
|
+
// 截取有效字节(避免空字符),解码为字符串
|
|
169
|
+
const validUint8Arr = uint8Arr.subarray(0, validLength);
|
|
170
|
+
return new TextDecoder('utf-8').decode(validUint8Arr);
|
|
171
|
+
}
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
ToRawJson(maxDepth = 4, visited = new WeakSet()) {
|
|
174
|
+
// 防护1:循环引用检测
|
|
175
|
+
if (visited.has(this)) {
|
|
176
|
+
return { "error": "circular reference" };
|
|
177
|
+
}
|
|
178
|
+
// 防护2:递归深度限制
|
|
179
|
+
if (maxDepth <= 0) {
|
|
180
|
+
return { "error": "exceed max recursion depth" };
|
|
181
|
+
}
|
|
182
|
+
visited.add(this);
|
|
183
|
+
const type = this.Type();
|
|
184
|
+
const count = this.Count();
|
|
185
|
+
try {
|
|
186
|
+
// 1. 空类型
|
|
187
|
+
if (NPack.IS_NULL(type)) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
// 2. 数字类型(非递归,直接返回值)
|
|
191
|
+
if (NPack.IS_NUMBER(type)) {
|
|
192
|
+
return this._parseNumber(type);
|
|
193
|
+
}
|
|
194
|
+
// 3. 字符串类型(非递归,直接返回值)
|
|
195
|
+
if (NPack.IS_BLOCK(type)) {
|
|
196
|
+
return this._parseString();
|
|
197
|
+
}
|
|
198
|
+
// 4. 数组类型(递归但有深度限制)
|
|
199
|
+
if (NPack.IS_ARRAY(type)) {
|
|
200
|
+
const arr = [];
|
|
201
|
+
for (let i = 0; i < count; i++) {
|
|
202
|
+
const member = this.GetMember(i);
|
|
203
|
+
arr.push(member ? member.ToRawJson(maxDepth - 1, visited) : null);
|
|
204
|
+
}
|
|
205
|
+
return arr;
|
|
206
|
+
}
|
|
207
|
+
// 5. 其他容器类型(结构/列表等,递归解析)
|
|
208
|
+
const retObjArray = [];
|
|
209
|
+
for (let i = 0; i < count; i++) {
|
|
210
|
+
const npackItem = this.GetMember(i);
|
|
211
|
+
retObjArray.push(npackItem ? npackItem.ToRawJson(maxDepth - 1, visited) : null);
|
|
212
|
+
}
|
|
213
|
+
return retObjArray;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
// 释放引用(避免内存泄漏)
|
|
217
|
+
visited.delete(this);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
ToJson(maxDepth = 4, visited = new WeakSet()) {
|
|
222
|
+
// 1. 直接调用 ToRawJson 拿到扁平键值对数组
|
|
223
|
+
const rawResult = this.ToRawJson(maxDepth, visited);
|
|
224
|
+
// 2. 处理错误场景(保持错误格式统一)
|
|
225
|
+
if (Array.isArray(rawResult) && rawResult[0] === "error") {
|
|
226
|
+
return { error: rawResult };
|
|
227
|
+
}
|
|
228
|
+
if (rawResult === null || typeof rawResult !== "object") {
|
|
229
|
+
return rawResult; // 基础类型(数字/字符串/null)直接返回
|
|
230
|
+
}
|
|
231
|
+
// 3. 工具函数:将单个 [k1,v1,k2,v2,...] 数组转为对象
|
|
232
|
+
const rawArrToObj = (rawArr) => {
|
|
233
|
+
const obj = {};
|
|
234
|
+
// 两两遍历数组:i 取 key,i+1 取 val,步长为2
|
|
235
|
+
for (let i = 0; i < rawArr.length; i += 2) {
|
|
236
|
+
const key = rawArr[i];
|
|
237
|
+
const val = rawArr[i + 1]; // 没有对应 val 时为 undefined
|
|
238
|
+
// 过滤无效 key(非字符串类型的 key 不存入对象)
|
|
239
|
+
if (typeof key === "string") {
|
|
240
|
+
// 递归处理 val:如果 val 是数组(子键值对),转为子对象
|
|
241
|
+
obj[key] = Array.isArray(val) && val[0] !== "error" ? rawArrToObj(val) : val;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return obj;
|
|
245
|
+
};
|
|
246
|
+
// 4. 区分外层是「二维数组」还是「单个键值对数组」
|
|
247
|
+
if (Array.isArray(rawResult)) {
|
|
248
|
+
// 情况1:外层是数组(如 [[k1,v1], [k2,v2]])→ 转为对象数组
|
|
249
|
+
if (rawResult.length > 0 && Array.isArray(rawResult[0])) {
|
|
250
|
+
return rawResult.map(item => Array.isArray(item) && item[0] !== "error" ? rawArrToObj(item) : item);
|
|
251
|
+
}
|
|
252
|
+
// 情况2:外层是单个键值对数组(如 [k1,v1,k2,v2])→ 转为单个对象
|
|
253
|
+
return rawArrToObj(rawResult);
|
|
254
|
+
}
|
|
255
|
+
// 5. 其他情况(如 PACK 类型返回的 ["k",3])→ 转为对象
|
|
256
|
+
return rawArrToObj(Array.isArray(rawResult) ? rawResult : []);
|
|
257
|
+
}
|
|
258
|
+
static Build(buffer, byteOffset) {
|
|
259
|
+
return new NPack(buffer, byteOffset);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { MixGramTypeEnum } from "../domain/enums/MixGramTypeEnum";
|
|
2
|
+
import { NPack } from "./NPack";
|
|
3
|
+
export declare enum RemoteBinDataTypeEnum {
|
|
4
|
+
R_EVENT_PACK = 4166,
|
|
5
|
+
R_DATAGRAM_LIST = 4224,
|
|
6
|
+
R_NULL = 0
|
|
7
|
+
}
|
|
8
|
+
export declare function RemoteBinDataType(buffer: Uint8Array): RemoteBinDataTypeEnum;
|
|
9
|
+
export declare enum RemoteDataGramListEnum {
|
|
10
|
+
R_DATAGRAM_FOR_VIN = 11954,
|
|
11
|
+
R_DATAGRAM_FOR_DIGITAL = 54467,
|
|
12
|
+
R_DATAGRAM_FOR_SWITCH = 9047,
|
|
13
|
+
R_DATAGRAM_FOR_CONTROLLER = 41961,
|
|
14
|
+
R_DATAGRAM_FOR_WATCH = 32604,
|
|
15
|
+
R_DATAGRAM_FOR_DATAGRAM = 63910
|
|
16
|
+
}
|
|
17
|
+
export declare enum RemoteEventPackTypeEnum {
|
|
18
|
+
R_EVENT_FOR_VIN_ATTR = 29005,
|
|
19
|
+
R_EVENT_FOR_ATS_EVENT = 50895
|
|
20
|
+
}
|
|
21
|
+
export declare class RemoteDataGramList {
|
|
22
|
+
m_buffer: Uint8Array;
|
|
23
|
+
m_dataview: DataView;
|
|
24
|
+
constructor(buffer: Uint8Array);
|
|
25
|
+
HeadSize(): number;
|
|
26
|
+
UnitSize(): number;
|
|
27
|
+
Type(): number;
|
|
28
|
+
MixGramTypeType(): MixGramTypeEnum;
|
|
29
|
+
HashId(): number;
|
|
30
|
+
InsId(): number;
|
|
31
|
+
ToJson(): object;
|
|
32
|
+
ToMixGramJson(type: MixGramTypeEnum): any;
|
|
33
|
+
DataGramList(): string[][];
|
|
34
|
+
ToDataGramJson(): any;
|
|
35
|
+
static Build(buffer: Uint8Array): RemoteDataGramList;
|
|
36
|
+
}
|
|
37
|
+
export declare class RemoteEventPack {
|
|
38
|
+
m_buffer: Uint8Array;
|
|
39
|
+
m_dataview: DataView;
|
|
40
|
+
m_pack: NPack;
|
|
41
|
+
constructor(buffer: Uint8Array);
|
|
42
|
+
HashId(): number;
|
|
43
|
+
static Build(buffer: Uint8Array): RemoteEventPack;
|
|
44
|
+
ToJson(): any;
|
|
45
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { DataGramUtil } from "./DataGramUtil";
|
|
2
|
+
import { MixGramTypeEnum } from "../domain/enums/MixGramTypeEnum";
|
|
3
|
+
import Dvb from "./Dvb";
|
|
4
|
+
import { NPack } from "./NPack";
|
|
5
|
+
export var RemoteBinDataTypeEnum;
|
|
6
|
+
(function (RemoteBinDataTypeEnum) {
|
|
7
|
+
RemoteBinDataTypeEnum[RemoteBinDataTypeEnum["R_EVENT_PACK"] = 4166] = "R_EVENT_PACK";
|
|
8
|
+
RemoteBinDataTypeEnum[RemoteBinDataTypeEnum["R_DATAGRAM_LIST"] = 4224] = "R_DATAGRAM_LIST";
|
|
9
|
+
RemoteBinDataTypeEnum[RemoteBinDataTypeEnum["R_NULL"] = 0] = "R_NULL";
|
|
10
|
+
})(RemoteBinDataTypeEnum || (RemoteBinDataTypeEnum = {}));
|
|
11
|
+
export function RemoteBinDataType(buffer) {
|
|
12
|
+
if (buffer[2] == 0x46) {
|
|
13
|
+
return RemoteBinDataTypeEnum.R_EVENT_PACK;
|
|
14
|
+
}
|
|
15
|
+
else if (buffer[2] == 0x80) {
|
|
16
|
+
return RemoteBinDataTypeEnum.R_DATAGRAM_LIST;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return RemoteBinDataTypeEnum.R_NULL;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export var RemoteDataGramListEnum;
|
|
23
|
+
(function (RemoteDataGramListEnum) {
|
|
24
|
+
RemoteDataGramListEnum[RemoteDataGramListEnum["R_DATAGRAM_FOR_VIN"] = 11954] = "R_DATAGRAM_FOR_VIN";
|
|
25
|
+
RemoteDataGramListEnum[RemoteDataGramListEnum["R_DATAGRAM_FOR_DIGITAL"] = 54467] = "R_DATAGRAM_FOR_DIGITAL";
|
|
26
|
+
RemoteDataGramListEnum[RemoteDataGramListEnum["R_DATAGRAM_FOR_SWITCH"] = 9047] = "R_DATAGRAM_FOR_SWITCH";
|
|
27
|
+
RemoteDataGramListEnum[RemoteDataGramListEnum["R_DATAGRAM_FOR_CONTROLLER"] = 41961] = "R_DATAGRAM_FOR_CONTROLLER";
|
|
28
|
+
RemoteDataGramListEnum[RemoteDataGramListEnum["R_DATAGRAM_FOR_WATCH"] = 32604] = "R_DATAGRAM_FOR_WATCH";
|
|
29
|
+
RemoteDataGramListEnum[RemoteDataGramListEnum["R_DATAGRAM_FOR_DATAGRAM"] = 63910] = "R_DATAGRAM_FOR_DATAGRAM";
|
|
30
|
+
})(RemoteDataGramListEnum || (RemoteDataGramListEnum = {}));
|
|
31
|
+
export var RemoteEventPackTypeEnum;
|
|
32
|
+
(function (RemoteEventPackTypeEnum) {
|
|
33
|
+
RemoteEventPackTypeEnum[RemoteEventPackTypeEnum["R_EVENT_FOR_VIN_ATTR"] = 29005] = "R_EVENT_FOR_VIN_ATTR";
|
|
34
|
+
RemoteEventPackTypeEnum[RemoteEventPackTypeEnum["R_EVENT_FOR_ATS_EVENT"] = 50895] = "R_EVENT_FOR_ATS_EVENT";
|
|
35
|
+
})(RemoteEventPackTypeEnum || (RemoteEventPackTypeEnum = {}));
|
|
36
|
+
export class RemoteDataGramList {
|
|
37
|
+
constructor(buffer) {
|
|
38
|
+
this.m_buffer = buffer;
|
|
39
|
+
this.m_dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
40
|
+
}
|
|
41
|
+
HeadSize() {
|
|
42
|
+
return 16;
|
|
43
|
+
}
|
|
44
|
+
UnitSize() {
|
|
45
|
+
return this.m_dataview.getUint16(6, true);
|
|
46
|
+
}
|
|
47
|
+
Type() {
|
|
48
|
+
return this.m_dataview.getUint16(2, true);
|
|
49
|
+
}
|
|
50
|
+
MixGramTypeType() {
|
|
51
|
+
const hashId = this.HashId();
|
|
52
|
+
switch (hashId) {
|
|
53
|
+
case RemoteDataGramListEnum.R_DATAGRAM_FOR_WATCH: return MixGramTypeEnum.WATCH;
|
|
54
|
+
case RemoteDataGramListEnum.R_DATAGRAM_FOR_DIGITAL: return MixGramTypeEnum.DI;
|
|
55
|
+
case RemoteDataGramListEnum.R_DATAGRAM_FOR_SWITCH: return MixGramTypeEnum.DO;
|
|
56
|
+
case RemoteDataGramListEnum.R_DATAGRAM_FOR_CONTROLLER: return MixGramTypeEnum.CTRL;
|
|
57
|
+
case RemoteDataGramListEnum.R_DATAGRAM_FOR_VIN: return MixGramTypeEnum.VIN;
|
|
58
|
+
case RemoteDataGramListEnum.R_DATAGRAM_FOR_DATAGRAM: return MixGramTypeEnum.GRAM;
|
|
59
|
+
}
|
|
60
|
+
return MixGramTypeEnum.OTHER;
|
|
61
|
+
}
|
|
62
|
+
HashId() {
|
|
63
|
+
return this.m_dataview.getUint16(4, true);
|
|
64
|
+
}
|
|
65
|
+
;
|
|
66
|
+
InsId() {
|
|
67
|
+
return this.m_dataview.getUint16(14, true);
|
|
68
|
+
}
|
|
69
|
+
ToJson() {
|
|
70
|
+
const mixGramTypeType = this.MixGramTypeType();
|
|
71
|
+
if (mixGramTypeType === MixGramTypeEnum.GRAM) {
|
|
72
|
+
return this.ToDataGramJson();
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
return this.ToMixGramJson(mixGramTypeType);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
ToMixGramJson(type) {
|
|
79
|
+
const dataGramList = this.DataGramList();
|
|
80
|
+
return {
|
|
81
|
+
"type": type,
|
|
82
|
+
"data": dataGramList[0],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
DataGramList() {
|
|
86
|
+
const hashId = this.HashId();
|
|
87
|
+
const tagLength = hashId == RemoteDataGramListEnum.R_DATAGRAM_FOR_DATAGRAM ? DataGramUtil.tagLength() : this.UnitSize() / 4;
|
|
88
|
+
if ((this.m_buffer.length - 16) % (tagLength * 4) != 0) {
|
|
89
|
+
console.error("length is err", tagLength, this.m_buffer.length);
|
|
90
|
+
return [[]];
|
|
91
|
+
}
|
|
92
|
+
const dataGramList = [];
|
|
93
|
+
// 单行长度 = 标签个数 × 4字节(uint32_t占4字节)
|
|
94
|
+
const singleLineLength = tagLength * 4;
|
|
95
|
+
const bodyDataSize = this.m_buffer.length - this.HeadSize();
|
|
96
|
+
for (let lineOffset = 0; lineOffset < bodyDataSize; lineOffset += singleLineLength) {
|
|
97
|
+
// 单个数据项的uint32数组(对应原line)
|
|
98
|
+
const singleLineItemList = [];
|
|
99
|
+
// 遍历当前数据项的所有标签,拼接4字节为uint32
|
|
100
|
+
for (let tagIdx = 0; tagIdx < tagLength; tagIdx++) {
|
|
101
|
+
// 计算当前标签在DataView中的字节偏移(行偏移 + 标签偏移×4字节)
|
|
102
|
+
const byteOffset = lineOffset + (tagIdx * 4) + 16;
|
|
103
|
+
const uint32Value = this.m_dataview.getUint32(byteOffset, true);
|
|
104
|
+
if (hashId != RemoteDataGramListEnum.R_DATAGRAM_FOR_DATAGRAM || DataGramUtil.isDVB(tagIdx)) {
|
|
105
|
+
const strValue = Dvb.Dvb2String(uint32Value);
|
|
106
|
+
singleLineItemList.push(strValue);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
singleLineItemList.push(uint32Value.toString(10));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
dataGramList.push(singleLineItemList);
|
|
113
|
+
}
|
|
114
|
+
return dataGramList;
|
|
115
|
+
}
|
|
116
|
+
ToDataGramJson() {
|
|
117
|
+
const retGramJson = {
|
|
118
|
+
"id": null,
|
|
119
|
+
"type": 1,
|
|
120
|
+
"result": {
|
|
121
|
+
"ctrlIndex": 0,
|
|
122
|
+
"data": {
|
|
123
|
+
"DataGramList": []
|
|
124
|
+
},
|
|
125
|
+
"msgEventType": 1,
|
|
126
|
+
"serviceType": 2
|
|
127
|
+
},
|
|
128
|
+
"slaveInstId": null,
|
|
129
|
+
"timestamp": 0
|
|
130
|
+
};
|
|
131
|
+
retGramJson.result.data.DataGramList = this.DataGramList();
|
|
132
|
+
return retGramJson;
|
|
133
|
+
}
|
|
134
|
+
static Build(buffer) {
|
|
135
|
+
return new RemoteDataGramList(buffer);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export class RemoteEventPack {
|
|
139
|
+
constructor(buffer) {
|
|
140
|
+
this.m_buffer = buffer;
|
|
141
|
+
this.m_dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
142
|
+
this.m_pack = NPack.Build(buffer, 16);
|
|
143
|
+
}
|
|
144
|
+
HashId() {
|
|
145
|
+
return this.m_dataview.getUint16(4, true);
|
|
146
|
+
}
|
|
147
|
+
;
|
|
148
|
+
static Build(buffer) {
|
|
149
|
+
return new RemoteEventPack(buffer);
|
|
150
|
+
}
|
|
151
|
+
ToJson() {
|
|
152
|
+
const mixGramTagMap = DataGramUtil.mixGramTagMap();
|
|
153
|
+
if (mixGramTagMap === null) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const hashId = this.HashId();
|
|
157
|
+
switch (hashId) {
|
|
158
|
+
case RemoteEventPackTypeEnum.R_EVENT_FOR_VIN_ATTR:
|
|
159
|
+
{
|
|
160
|
+
const vinTagList = mixGramTagMap[MixGramTypeEnum.VIN];
|
|
161
|
+
const vinAttrList = this.m_pack.ToJson();
|
|
162
|
+
const retJson = {};
|
|
163
|
+
for (let i = 0; i < vinAttrList.length; i++) {
|
|
164
|
+
retJson[vinTagList[i]] = vinAttrList[i];
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
"type": MixGramTypeEnum.VIN_ATTR,
|
|
168
|
+
"data": retJson
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
case RemoteEventPackTypeEnum.R_EVENT_FOR_ATS_EVENT: {
|
|
172
|
+
return {
|
|
173
|
+
"type": MixGramTypeEnum.OTHER,
|
|
174
|
+
"data": this.m_pack.ToJson()
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|