@miot-rn/common-component 1.0.1
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/README.md +9 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -0
- package/dist/resources/i18n.d.ts +55 -0
- package/dist/resources/i18n.js +212 -0
- package/dist/service/specs/error-code.d.ts +19 -0
- package/dist/service/specs/error-code.js +41 -0
- package/dist/service/specs/index.d.ts +95 -0
- package/dist/service/specs/index.js +412 -0
- package/dist/service/specs/spec.d.ts +10 -0
- package/dist/service/specs/spec.js +109 -0
- package/dist/service/specs/specCache.d.ts +85 -0
- package/dist/service/specs/specCache.js +421 -0
- package/dist/service/specs/std-spec.d.ts +5 -0
- package/dist/service/specs/std-spec.js +228 -0
- package/dist/service/specs/subject.d.ts +20 -0
- package/dist/service/specs/subject.js +145 -0
- package/dist/service/specs/utils.d.ts +28 -0
- package/dist/service/specs/utils.js +46 -0
- package/dist/specs/i18n-parser.d.ts +10 -0
- package/dist/specs/i18n-parser.js +300 -0
- package/dist/specs/instance-parser.d.ts +26 -0
- package/dist/specs/instance-parser.js +706 -0
- package/dist/store/useGlobalSpecManager.d.ts +320 -0
- package/dist/store/useGlobalSpecManager.js +867 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/fns.d.ts +12 -0
- package/dist/utils/fns.js +308 -0
- package/dist/utils/get-value-or-default.d.ts +1 -0
- package/dist/utils/get-value-or-default.js +4 -0
- package/dist/utils/i18n.d.ts +1 -0
- package/dist/utils/i18n.js +141 -0
- package/dist/utils/objects.d.ts +2 -0
- package/dist/utils/objects.js +222 -0
- package/dist/utils/spec.d.ts +8 -0
- package/dist/utils/spec.js +171 -0
- package/dist/utils/types.d.ts +3 -0
- package/dist/utils/types.js +25 -0
- package/package.json +27 -0
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
/* eslint-disable no-use-before-define, @typescript-eslint/no-use-before-define, @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { isSpecProp } from "../utils/spec";
|
|
3
|
+
import { safeTrim } from "../utils/fns";
|
|
4
|
+
let CachedInstance = null;
|
|
5
|
+
let CachedIidsGetter = null;
|
|
6
|
+
let CachedSpecVersion = null;
|
|
7
|
+
const QuerySpecsCache = {};
|
|
8
|
+
// 初始化,记录instance, 方便后续直接使用
|
|
9
|
+
export function init(instance) {
|
|
10
|
+
if (instance) {
|
|
11
|
+
setCachedInstance(instance);
|
|
12
|
+
setCachedSpecVersion(instance);
|
|
13
|
+
setCachedIidsGetter(instance);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function setCachedInstance(instance) {
|
|
17
|
+
CachedInstance = instance;
|
|
18
|
+
}
|
|
19
|
+
export function getInstance() {
|
|
20
|
+
return CachedInstance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 设置缓存的规格版本
|
|
25
|
+
* @param {Object} instance - 设备实例对象
|
|
26
|
+
*/
|
|
27
|
+
function setCachedSpecVersion(instance) {
|
|
28
|
+
// 根据protocol-version字段获取版本,如果不存在则根据modules数组判断
|
|
29
|
+
if (instance?.['protocol-version']) {
|
|
30
|
+
// 将protocol-version字符串转为整数类型,如"3.0"转为3
|
|
31
|
+
const versionStr = instance['protocol-version'].split('.')[0];
|
|
32
|
+
CachedSpecVersion = parseInt(versionStr, 10) || 2;
|
|
33
|
+
} else {
|
|
34
|
+
// 如果没有protocol-version字段,则为specV2版本
|
|
35
|
+
CachedSpecVersion = 2;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 获取当前缓存的规格版本
|
|
41
|
+
* @returns {number} - 规格版本号
|
|
42
|
+
*/
|
|
43
|
+
export function getSpecVersion() {
|
|
44
|
+
return CachedSpecVersion;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 获取动态类型
|
|
49
|
+
* @returns {number} - 动态类型值,如果不存在则默认为0
|
|
50
|
+
*/
|
|
51
|
+
export function getDynamicType() {
|
|
52
|
+
// 从instance中直接获取dynamic字段,如果不存在则默认为0
|
|
53
|
+
return CachedInstance?.dynamic !== undefined ? Number(CachedInstance.dynamic) : 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 获取有效的模块列表
|
|
58
|
+
* @returns {Array} - 返回有效的模块数组
|
|
59
|
+
*/
|
|
60
|
+
export function getValidModules() {
|
|
61
|
+
const specVersion = getSpecVersion();
|
|
62
|
+
// 如果是版本2,返回包含整个实例的数组
|
|
63
|
+
// 如果是版本3,返回所有模块,但排除名为'basic'的模块
|
|
64
|
+
return specVersion < 3 ? [CachedInstance] : CachedInstance?.modules || [];
|
|
65
|
+
}
|
|
66
|
+
function setCachedIidsGetter(_instance) {
|
|
67
|
+
CachedIidsGetter = getIidsGetter();
|
|
68
|
+
}
|
|
69
|
+
export function parseSpecType(type) {
|
|
70
|
+
return CachedSpecVersion === 3 ? parseSpecType3(type) : parseSpecType2(type);
|
|
71
|
+
}
|
|
72
|
+
function parseSpecType2(type) {
|
|
73
|
+
const splited = (type || '').split(':');
|
|
74
|
+
return {
|
|
75
|
+
key: splited[3],
|
|
76
|
+
version: parseInt(splited[6], 10)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function parseSpecType3(type) {
|
|
80
|
+
const [std] = (type || '').split(';');
|
|
81
|
+
const splitStd = (std || '').split(':');
|
|
82
|
+
return {
|
|
83
|
+
key: splitStd[4],
|
|
84
|
+
version: parseInt(splitStd[6], 10) || 0
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 创建规格查询函数
|
|
90
|
+
* @returns {Function} - 返回规格查询函数
|
|
91
|
+
*/
|
|
92
|
+
function getIidsGetter() {
|
|
93
|
+
/**
|
|
94
|
+
* 根据查询参数获取规格信息
|
|
95
|
+
* @param {QuerySpecParams} params - 查询参数
|
|
96
|
+
* @returns {Array} - 返回匹配的规格数组
|
|
97
|
+
*/
|
|
98
|
+
return function querySpecs(params = {}) {
|
|
99
|
+
// 解构参数
|
|
100
|
+
const {
|
|
101
|
+
mkey,
|
|
102
|
+
mDescription,
|
|
103
|
+
skey,
|
|
104
|
+
sDescription,
|
|
105
|
+
pkey,
|
|
106
|
+
akey,
|
|
107
|
+
ekey,
|
|
108
|
+
description,
|
|
109
|
+
dataSource
|
|
110
|
+
} = params;
|
|
111
|
+
|
|
112
|
+
// 预处理描述类字段,规避人为空格导致的错配
|
|
113
|
+
const normalizedMKey = safeTrim(mkey);
|
|
114
|
+
const normalizedMDescription = safeTrim(mDescription);
|
|
115
|
+
const normalizedSDescription = safeTrim(sDescription);
|
|
116
|
+
const normalizedDescription = safeTrim(description);
|
|
117
|
+
// console.log('querySpecs-----params', params);
|
|
118
|
+
// console.log('querySpecs-----CachedInstance', CachedInstance);
|
|
119
|
+
// console.log('querySpecs-----protocol-version', CachedInstance?.['protocol-version'], CachedSpecVersion);
|
|
120
|
+
|
|
121
|
+
// 基本参数验证
|
|
122
|
+
if (!skey || !pkey && !akey && !ekey) {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 生成缓存键
|
|
127
|
+
const cacheKey = `${ekey ? 'event' : akey ? 'action' : 'prop'}:${normalizedMDescription || '-'}:${normalizedMKey || '-'}:${normalizedSDescription || '-'}:${skey}:${normalizedDescription || '-'}:${ekey || akey || pkey}`;
|
|
128
|
+
|
|
129
|
+
// 检查缓存
|
|
130
|
+
if (cacheKey in QuerySpecsCache) {
|
|
131
|
+
return QuerySpecsCache[cacheKey];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 获取目标模块
|
|
135
|
+
const targetModule = findModuleByKeyAndDescription(normalizedMKey, normalizedMDescription);
|
|
136
|
+
// console.log('targetModule---', targetModule);
|
|
137
|
+
|
|
138
|
+
if (!targetModule && mkey) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 查找匹配的服务
|
|
143
|
+
const services = (targetModule?.services || []).filter(service => {
|
|
144
|
+
return parseSpecType(service.type).key === skey && (!normalizedSDescription || normalizedSDescription === safeTrim(service.description));
|
|
145
|
+
}).reverse();
|
|
146
|
+
if (!services.length) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 存储结果的数组
|
|
151
|
+
const result = [];
|
|
152
|
+
|
|
153
|
+
// 处理服务版本控制
|
|
154
|
+
// 按描述分组,每个描述组内独立进行版本控制
|
|
155
|
+
const serviceGroups = {};
|
|
156
|
+
|
|
157
|
+
// 将服务按描述分组
|
|
158
|
+
for (const service of services) {
|
|
159
|
+
const serviceDescription = safeTrim(service.description) || '';
|
|
160
|
+
const serviceVersion = parseSpecType(service.type).version;
|
|
161
|
+
if (!serviceGroups[serviceDescription]) {
|
|
162
|
+
serviceGroups[serviceDescription] = serviceVersion;
|
|
163
|
+
}
|
|
164
|
+
// console.log('serviceVersion--', serviceVersion);
|
|
165
|
+
// console.log('serviceGroups[serviceDescription]--', serviceGroups[serviceDescription]);
|
|
166
|
+
|
|
167
|
+
// 版本控制,只处理最新版本
|
|
168
|
+
if (serviceVersion < serviceGroups[serviceDescription]) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
// 获取属性/动作/事件列表
|
|
172
|
+
const propertyType = ekey ? 'events' : akey ? 'actions' : 'properties';
|
|
173
|
+
// console.log('propertyType--', propertyType);
|
|
174
|
+
const items = service[propertyType] || [];
|
|
175
|
+
|
|
176
|
+
// 查找匹配的属性/动作/事件
|
|
177
|
+
const matchedItems = items.filter(item => {
|
|
178
|
+
return parseSpecType(item.type).key === (ekey || akey || pkey) && (!normalizedDescription || normalizedDescription === safeTrim(item.description));
|
|
179
|
+
}).reverse();
|
|
180
|
+
// 按描述分组,每个描述组内独立进行版本控制
|
|
181
|
+
const itemGroups = {};
|
|
182
|
+
|
|
183
|
+
// 将属性/动作/事件按描述分组
|
|
184
|
+
for (const item of matchedItems) {
|
|
185
|
+
const itemDescription = safeTrim(item.description) || '';
|
|
186
|
+
const itemVersion = parseSpecType(item.type).version;
|
|
187
|
+
if (!itemGroups[itemDescription]) {
|
|
188
|
+
itemGroups[itemDescription] = itemVersion;
|
|
189
|
+
}
|
|
190
|
+
// 版本控制,只处理最新版本
|
|
191
|
+
if (itemVersion < itemGroups[itemDescription]) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
// 处理过滤后的属性/动作/事件
|
|
195
|
+
// 构建规格对象
|
|
196
|
+
const spec = {
|
|
197
|
+
siid: service.iid,
|
|
198
|
+
[ekey ? 'eiid' : akey ? 'aiid' : 'piid']: item.iid,
|
|
199
|
+
skey,
|
|
200
|
+
[ekey ? 'ekey' : akey ? 'akey' : 'pkey']: ekey || akey || pkey,
|
|
201
|
+
service,
|
|
202
|
+
[ekey ? 'event' : akey ? 'action' : 'prop']: item,
|
|
203
|
+
dataSource,
|
|
204
|
+
source: item.source,
|
|
205
|
+
sDescription: serviceDescription
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// 添加特定类型的属性
|
|
209
|
+
if (ekey) {
|
|
210
|
+
spec.arguments = item.arguments || [];
|
|
211
|
+
} else if (akey) {
|
|
212
|
+
spec.in = item.in || [];
|
|
213
|
+
spec.out = item.out || [];
|
|
214
|
+
} else if (pkey) {
|
|
215
|
+
// 处理属性相关事件
|
|
216
|
+
const events = service.events || [];
|
|
217
|
+
const relatedEvents = events.filter(event => {
|
|
218
|
+
return event && event.arguments && event.arguments.includes(item.iid);
|
|
219
|
+
});
|
|
220
|
+
if (relatedEvents.length) {
|
|
221
|
+
spec.reiids = relatedEvents.map(event => event.iid);
|
|
222
|
+
spec.reIndexs = relatedEvents.map(event => event.arguments.findIndex(iid => iid === item.iid));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 添加模块信息
|
|
227
|
+
if (mkey && targetModule) {
|
|
228
|
+
spec.miid = targetModule?.iid;
|
|
229
|
+
spec.mkey = mkey || parseSpecType(targetModule?.type).key;
|
|
230
|
+
spec.mDescription = normalizedMDescription;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 将最新版本的结果添加到数组开头
|
|
234
|
+
result.unshift(spec);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// 缓存结果
|
|
239
|
+
QuerySpecsCache[cacheKey] = result;
|
|
240
|
+
return result;
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 根据查询参数数组获取对应的规格信息
|
|
246
|
+
* @param {Array<QuerySpecParams>} keys - 查询参数数组,每个元素包含 {skey, pkey}, {skey, akey}, {skey, ekey} 等
|
|
247
|
+
* @returns {Array<Array<Object>>} - 返回二维数组,每个子数组包含匹配的规格信息 [{skey, pkey, siid, piid, service, prop}]
|
|
248
|
+
*/
|
|
249
|
+
export function getSpecs(keys) {
|
|
250
|
+
// 参数验证
|
|
251
|
+
if (!Array.isArray(keys)) {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// 使用缓存查询函数处理每个查询参数
|
|
256
|
+
return keys.map(queryParams => {
|
|
257
|
+
// 支持模块和描述等特殊逻辑
|
|
258
|
+
return CachedIidsGetter(queryParams);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* 根据查询参数数组获取对应的规格信息中的第一项
|
|
264
|
+
* @param {Array<QuerySpecParams>} keys - 查询参数数组,每个元素包含 {skey, pkey}, {skey, akey}, {skey, ekey} 等
|
|
265
|
+
* @returns {Array<Object|null>} - 返回一维数组,每个元素是匹配的规格信息中的第一项或null [{skey, pkey, siid, piid, service, prop}]
|
|
266
|
+
*/
|
|
267
|
+
export function getSpecsOnly(keys) {
|
|
268
|
+
// 参数验证
|
|
269
|
+
if (!Array.isArray(keys)) {
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 使用缓存查询函数处理每个查询参数,并只取每个结果的第一项
|
|
274
|
+
return keys.map(queryParams => {
|
|
275
|
+
const specs = CachedIidsGetter(queryParams);
|
|
276
|
+
return specs && specs.length > 0 ? specs[0] : null;
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* 根据单个查询参数获取对应的规格信息中的第一项
|
|
282
|
+
* @param {QuerySpecParams} key - 查询参数,包含 {skey, pkey}, {skey, akey}, {skey, ekey} 等
|
|
283
|
+
* @returns {Object|null} - 返回匹配的规格信息中的第一项或null {skey, pkey, siid, piid, service, prop}
|
|
284
|
+
*/
|
|
285
|
+
export function getSpecOnly(key) {
|
|
286
|
+
const result = getSpecsOnly([key]);
|
|
287
|
+
return result.length > 0 ? result[0] : null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* 根据传入的属性(包括spec属性和虚拟属性),获取其IID信息
|
|
292
|
+
* @param {Array<Object>} specs - 规格数组,每个元素包含 {skey, pkey, siid, piid, prop, service, ...}
|
|
293
|
+
* @returns {Array<Object>} - 返回包含IID信息的数组 [{siid, piid, access, format, ...}]
|
|
294
|
+
*/
|
|
295
|
+
export function getSpecsIidsOnly(specs) {
|
|
296
|
+
// 参数验证
|
|
297
|
+
if (!Array.isArray(specs)) {
|
|
298
|
+
return [];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// 处理每个规格对象
|
|
302
|
+
return specs.map(spec => {
|
|
303
|
+
// 如果是虚拟属性,直接原样返回
|
|
304
|
+
if (!isSpecProp(spec)) {
|
|
305
|
+
return spec ? {
|
|
306
|
+
...spec
|
|
307
|
+
} : spec;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// 提取属性类型ID(piid/aiid/eiid)
|
|
311
|
+
const propertyIdKey = 'eiid' in spec ? 'eiid' : 'aiid' in spec ? 'aiid' : 'piid';
|
|
312
|
+
const propertyIdValue = 'eiid' in spec ? spec.eiid : 'aiid' in spec ? spec.aiid : spec.piid;
|
|
313
|
+
|
|
314
|
+
// 构建IID信息对象
|
|
315
|
+
return {
|
|
316
|
+
access: spec.prop ? spec.prop.access : [],
|
|
317
|
+
'gatt-access': spec.prop ? spec.prop['gatt-access'] : [],
|
|
318
|
+
format: spec.prop ? spec.prop.format : '',
|
|
319
|
+
miid: spec.miid,
|
|
320
|
+
siid: spec.siid,
|
|
321
|
+
[propertyIdKey]: propertyIdValue,
|
|
322
|
+
in: spec.in || [],
|
|
323
|
+
reiids: spec.reiids || [],
|
|
324
|
+
reIndexs: spec.reIndexs || [],
|
|
325
|
+
dataSource: spec.dataSource,
|
|
326
|
+
source: spec.source
|
|
327
|
+
};
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 查找 spec value-list 中 targetValue 对应的 index
|
|
333
|
+
* 如果找不到匹配的值,则返回-1。
|
|
334
|
+
*
|
|
335
|
+
* @param {object} spec - 包含规范的对象。
|
|
336
|
+
* @param {any} targetValue - 要查找的目标值。
|
|
337
|
+
* @returns {number} - 如果找到匹配的值,返回该值在'value-list'中的索引;否则返回-1。
|
|
338
|
+
*/
|
|
339
|
+
export function getIndexBySpecValue(spec, targetValue) {
|
|
340
|
+
const valueList = (spec?.prop?.['value-list'] || []).filter(item => item && item.value !== undefined);
|
|
341
|
+
const index = valueList.findIndex(item => item.value === targetValue);
|
|
342
|
+
return index;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* 获取 value-list
|
|
347
|
+
* 如果不存在,返回 []。
|
|
348
|
+
*
|
|
349
|
+
* @param {object} spec - 包含规范的对象。
|
|
350
|
+
* @returns {Array} - 如果找到匹配的值,返回在'value-list'的值。
|
|
351
|
+
*/
|
|
352
|
+
export function getSpecValueList(spec) {
|
|
353
|
+
// @ts-ignore
|
|
354
|
+
return (spec?.prop?.['value-list'] || []).filter(item => item && item.value !== undefined);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* 获取spec value-list 中对应description 的value
|
|
359
|
+
* @param {object} spec 目标属性
|
|
360
|
+
* @param {string} description 目标description
|
|
361
|
+
* @return {any} value 通常是number
|
|
362
|
+
*/
|
|
363
|
+
export function getValueBySpecDescription(spec, description) {
|
|
364
|
+
// @ts-ignore
|
|
365
|
+
const vl = spec && spec.prop && spec.prop['value-list'] ? spec.prop['value-list'] : [];
|
|
366
|
+
const normalizedDescription = safeTrim(description);
|
|
367
|
+
const value = (vl || []).find(v => {
|
|
368
|
+
const vDesc = safeTrim(v?.description) || '';
|
|
369
|
+
return v && vDesc.toLowerCase() === (normalizedDescription || '').toLowerCase();
|
|
370
|
+
});
|
|
371
|
+
return value ? value.value : undefined;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* 获取 value-range
|
|
376
|
+
* 如果不存在,返回 []。
|
|
377
|
+
*
|
|
378
|
+
* @param {object} spec - 包含规范的对象。
|
|
379
|
+
* @returns {Array} - 如果找到匹配的值,返回在'value-range'的值。
|
|
380
|
+
*/
|
|
381
|
+
export function getSpecValueRange(spec) {
|
|
382
|
+
// @ts-ignore
|
|
383
|
+
return spec?.prop?.['value-range'] || [];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* 获取spec value-list 中对应description 的index
|
|
388
|
+
* @param {object} spec 目标属性
|
|
389
|
+
* @param {string} description 目标description
|
|
390
|
+
* @return {any} value 通常是number
|
|
391
|
+
*/
|
|
392
|
+
export function getIndexBySpecDescription(spec, description) {
|
|
393
|
+
// @ts-ignore
|
|
394
|
+
const vl = spec && spec.prop && spec.prop['value-list'] ? spec.prop['value-list'] : [];
|
|
395
|
+
const normalizedDescription = safeTrim(description);
|
|
396
|
+
let ans = -1;
|
|
397
|
+
(vl || []).forEach((v, index) => {
|
|
398
|
+
const vDesc = safeTrim(v?.description) || '';
|
|
399
|
+
if (v && vDesc.toLowerCase() === (normalizedDescription || '').toLowerCase()) {
|
|
400
|
+
ans = index;
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
return ans;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* 获取spec value-list 中对应description 的value,主要作用是兼容不规范的description
|
|
408
|
+
* 注意有优先级,先取前面的,取不到再取后面的
|
|
409
|
+
* @param {object} spec 目标属性
|
|
410
|
+
* @param {string} descriptions 目标descriptions, 从多个descriptions 中匹配出一个即可
|
|
411
|
+
* @return {any} value 通常是number
|
|
412
|
+
*/
|
|
413
|
+
export function getValueBySpecDescriptions(spec, descriptions = []) {
|
|
414
|
+
for (let i = 0, l = descriptions.length; i < l; i++) {
|
|
415
|
+
const v = getValueBySpecDescription(spec, safeTrim(descriptions[i]));
|
|
416
|
+
if (![undefined, null].includes(v)) {
|
|
417
|
+
return v;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* 获取value-list 中idle/none 状态的索引
|
|
425
|
+
* @param {object} spec 目标属性
|
|
426
|
+
* @return {number} index
|
|
427
|
+
*/
|
|
428
|
+
export function getIdleIndex(spec) {
|
|
429
|
+
// @ts-ignore
|
|
430
|
+
if (!spec || !spec.prop || !spec.prop['value-list']) {
|
|
431
|
+
return -1;
|
|
432
|
+
}
|
|
433
|
+
// @ts-ignore
|
|
434
|
+
return spec.prop['value-list'].findIndex(({
|
|
435
|
+
description
|
|
436
|
+
}) => {
|
|
437
|
+
return ['Idle', 'None'].includes(description);
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* 获取 instance 中的属性索引
|
|
443
|
+
* @param {object} instance
|
|
444
|
+
* @param {skey, pkey} search
|
|
445
|
+
* @returns
|
|
446
|
+
*/
|
|
447
|
+
export function getKeyIndexOfInstance(instance, search) {
|
|
448
|
+
const serviceIndex = (instance?.services || []).findIndex(item => {
|
|
449
|
+
return parseSpecType(item?.type).key === search.skey;
|
|
450
|
+
});
|
|
451
|
+
const propertyIndex = ((instance?.services?.[serviceIndex] || {}).properties || []).findIndex(item => {
|
|
452
|
+
return parseSpecType(item?.type).key === search.pkey;
|
|
453
|
+
});
|
|
454
|
+
return [serviceIndex, propertyIndex];
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* 根据IID信息确定要查找的属性类型
|
|
459
|
+
* @param {Object} iidInfo - 包含 piid, aiid, eiid 的对象
|
|
460
|
+
* @returns {string} - 返回 'properties', 'actions', 'events' 或 'unknown'
|
|
461
|
+
*/
|
|
462
|
+
function determinePropertyType({
|
|
463
|
+
piid,
|
|
464
|
+
aiid,
|
|
465
|
+
eiid
|
|
466
|
+
}) {
|
|
467
|
+
if (piid) return 'properties';
|
|
468
|
+
if (aiid) return 'actions';
|
|
469
|
+
if (eiid) return 'events';
|
|
470
|
+
return 'unknown';
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* 根据IID信息确定属性ID的键名
|
|
475
|
+
* @param {Object} iidInfo - 包含 piid, aiid, eiid 的对象
|
|
476
|
+
* @returns {string} - 返回 'piid', 'aiid' 或 'eiid'
|
|
477
|
+
*/
|
|
478
|
+
function determinePropertyIdKey({
|
|
479
|
+
piid,
|
|
480
|
+
aiid,
|
|
481
|
+
eiid
|
|
482
|
+
}) {
|
|
483
|
+
if (piid) return 'piid';
|
|
484
|
+
if (aiid) return 'aiid';
|
|
485
|
+
if (eiid) return 'eiid';
|
|
486
|
+
return 'unknown';
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* 根据IID信息确定spec键名
|
|
491
|
+
* @param {Object} iidInfo - 包含 piid, aiid, eiid 的对象
|
|
492
|
+
* @returns {string} - 返回 'pkey', 'akey' 或 'ekey'
|
|
493
|
+
*/
|
|
494
|
+
function determineSpecKey({
|
|
495
|
+
piid,
|
|
496
|
+
aiid,
|
|
497
|
+
eiid
|
|
498
|
+
}) {
|
|
499
|
+
if (piid) return 'pkey';
|
|
500
|
+
if (aiid) return 'akey';
|
|
501
|
+
if (eiid) return 'ekey';
|
|
502
|
+
return 'unknown';
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* 根据IID信息确定spec属性名
|
|
507
|
+
* @param {Object} iidInfo - 包含 piid, aiid, eiid 的对象
|
|
508
|
+
* @returns {string} - 返回 'prop', 'action' 或 'event'
|
|
509
|
+
*/
|
|
510
|
+
function determineSpecProperty({
|
|
511
|
+
piid,
|
|
512
|
+
aiid,
|
|
513
|
+
eiid
|
|
514
|
+
}) {
|
|
515
|
+
if (piid) return 'prop';
|
|
516
|
+
if (aiid) return 'action';
|
|
517
|
+
if (eiid) return 'event';
|
|
518
|
+
return 'unknown';
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* 验证IID信息是否有效
|
|
523
|
+
* @param {Object} iidInfo - 包含 siid, piid, aiid, eiid, miid 的对象
|
|
524
|
+
* @returns {boolean} - 如果有效返回true,否则返回false
|
|
525
|
+
*/
|
|
526
|
+
function isValidIidInfo(iidInfo) {
|
|
527
|
+
if (!iidInfo) return false;
|
|
528
|
+
const {
|
|
529
|
+
siid,
|
|
530
|
+
piid,
|
|
531
|
+
aiid,
|
|
532
|
+
eiid,
|
|
533
|
+
miid
|
|
534
|
+
} = iidInfo;
|
|
535
|
+
|
|
536
|
+
// 规格版本3需要提供miid
|
|
537
|
+
if (CachedSpecVersion === 3 && !miid) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
return siid && (piid || aiid || eiid);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* 获取目标模块
|
|
545
|
+
* @param {number} miid - 模块ID
|
|
546
|
+
* @returns {Object|null} - 返回目标模块对象或null
|
|
547
|
+
*/
|
|
548
|
+
function getTargetModule(miid) {
|
|
549
|
+
// 如果是版本3,根据miid查找对应模块
|
|
550
|
+
if (CachedSpecVersion === 3) {
|
|
551
|
+
return (CachedInstance.modules || []).find(module => {
|
|
552
|
+
return module?.iid === miid;
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
// 如果是版本2,直接返回整个实例
|
|
556
|
+
return CachedInstance;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* 根据mkey和mDescription查找模块
|
|
561
|
+
* @param {string} mkey - 模块键
|
|
562
|
+
* @param {string} mDescription - 模块描述(可选)
|
|
563
|
+
* @returns {Object|null} - 返回目标模块对象或null
|
|
564
|
+
*/
|
|
565
|
+
function findModuleByKeyAndDescription(mkey, mDescription) {
|
|
566
|
+
const normalizedMKey = safeTrim(mkey);
|
|
567
|
+
const normalizedMDescription = safeTrim(mDescription);
|
|
568
|
+
// 如果是版本3
|
|
569
|
+
if (CachedSpecVersion === 3) {
|
|
570
|
+
return (CachedInstance.modules || []).find(module => {
|
|
571
|
+
const moduleDescription = safeTrim(module?.description);
|
|
572
|
+
const moduleName = safeTrim(module?.name);
|
|
573
|
+
// 如果提供了mDescription,同时匹配mkey和mDescription
|
|
574
|
+
if (normalizedMDescription) {
|
|
575
|
+
return moduleName === normalizedMKey && moduleDescription === normalizedMDescription;
|
|
576
|
+
}
|
|
577
|
+
// 只匹配mkey
|
|
578
|
+
return moduleName === normalizedMKey;
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
// 如果是版本2,返回整个实例
|
|
582
|
+
return CachedInstance;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* 获取目标服务
|
|
587
|
+
* @param {Object} module - 模块对象
|
|
588
|
+
* @param {number} siid - 服务ID
|
|
589
|
+
* @returns {Object} - 返回目标服务对象
|
|
590
|
+
*/
|
|
591
|
+
function getTargetService(module, siid) {
|
|
592
|
+
return (module?.services || []).find(service => {
|
|
593
|
+
return service?.iid === siid;
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* 获取目标属性/动作/事件
|
|
599
|
+
* @param {Object} service - 服务对象
|
|
600
|
+
* @param {Object} iidInfo - 包含 piid, aiid, eiid 的对象
|
|
601
|
+
* @returns {Object} - 返回目标属性/动作/事件对象
|
|
602
|
+
*/
|
|
603
|
+
function getTargetProperty(service, iidInfo) {
|
|
604
|
+
const propertyType = determinePropertyType(iidInfo);
|
|
605
|
+
if (propertyType === 'unknown') return null;
|
|
606
|
+
const {
|
|
607
|
+
piid,
|
|
608
|
+
aiid
|
|
609
|
+
} = iidInfo;
|
|
610
|
+
const propertyId = iidInfo[piid ? 'piid' : aiid ? 'aiid' : 'eiid'];
|
|
611
|
+
const properties = service[propertyType] || [];
|
|
612
|
+
return properties.find(pae => {
|
|
613
|
+
return pae?.iid === propertyId;
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* 构建规范对象
|
|
619
|
+
* @param {Object} iidInfo - IID信息
|
|
620
|
+
* @param {Object} service - 服务对象
|
|
621
|
+
* @param {Object} property - 属性/动作/事件对象
|
|
622
|
+
* @param {Object} module - 模块对象
|
|
623
|
+
* @returns {Object} - 返回构建的规范对象
|
|
624
|
+
*/
|
|
625
|
+
function buildSpecObject(iidInfo, service, property, module) {
|
|
626
|
+
const {
|
|
627
|
+
siid,
|
|
628
|
+
miid
|
|
629
|
+
} = iidInfo;
|
|
630
|
+
const propertyIdKey = determinePropertyIdKey(iidInfo);
|
|
631
|
+
const specKey = determineSpecKey(iidInfo);
|
|
632
|
+
const specProperty = determineSpecProperty(iidInfo);
|
|
633
|
+
const spec = {
|
|
634
|
+
siid,
|
|
635
|
+
[propertyIdKey]: property.iid,
|
|
636
|
+
skey: parseSpecType(service.type)?.key,
|
|
637
|
+
[specKey]: parseSpecType(property.type)?.key,
|
|
638
|
+
service,
|
|
639
|
+
[specProperty]: property,
|
|
640
|
+
source: property.source
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
// 如果是规格版本3,添加模块相关信息
|
|
644
|
+
if (CachedSpecVersion === 3) {
|
|
645
|
+
spec.miid = miid;
|
|
646
|
+
spec.mkey = parseSpecType(module.type)?.key;
|
|
647
|
+
}
|
|
648
|
+
return spec;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* 根据IID获取规范信息
|
|
653
|
+
* @param {Object} iidInfo - 包含 {miid, siid, piid, aiid, eiid} 的对象
|
|
654
|
+
* @returns {Object|null} - 返回规范对象或null
|
|
655
|
+
*/
|
|
656
|
+
function getSpecByIid(iidInfo) {
|
|
657
|
+
// 验证IID信息是否有效
|
|
658
|
+
if (!isValidIidInfo(iidInfo)) {
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
const {
|
|
662
|
+
miid,
|
|
663
|
+
siid
|
|
664
|
+
} = iidInfo;
|
|
665
|
+
|
|
666
|
+
// 验证miid是否提供(规格版本3需要)
|
|
667
|
+
if (CachedSpecVersion === 3 && !miid) {
|
|
668
|
+
return null;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// 获取目标模块
|
|
672
|
+
const targetModule = getTargetModule(miid);
|
|
673
|
+
if (!targetModule) {
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// 获取目标服务
|
|
678
|
+
const targetService = getTargetService(targetModule, siid);
|
|
679
|
+
if (!targetService) {
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// 获取目标属性/动作/事件
|
|
684
|
+
const targetProperty = getTargetProperty(targetService, iidInfo);
|
|
685
|
+
if (!targetProperty) {
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// 构建并返回规范对象
|
|
690
|
+
return buildSpecObject(iidInfo, targetService, targetProperty, targetModule);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* 根据IID数组获取规范信息数组
|
|
695
|
+
* @param {Array} iids - 包含多个IID对象的数组,每个对象格式为 {miid, siid, piid, aiid, eiid}
|
|
696
|
+
* @returns {Array} - 返回规范对象数组
|
|
697
|
+
*/
|
|
698
|
+
export function getSpecsByIids(iids) {
|
|
699
|
+
// 参数验证
|
|
700
|
+
if (!CachedInstance || !Array.isArray(iids) || iids.length === 0) {
|
|
701
|
+
return [];
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// 遍历IID数组,获取每个IID对应的规范信息
|
|
705
|
+
return iids.map(iidInfo => getSpecByIid(iidInfo));
|
|
706
|
+
}
|