nayota-show-sdk 1.3.73 → 1.3.75
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/utils/iot-module-specs.js +131 -14
- package/utils/iot-module-specs.test.js +54 -14
package/package.json
CHANGED
|
@@ -360,6 +360,60 @@ function normalizeLegacyPropLine(source = {}, prop = {}, row = {}) {
|
|
|
360
360
|
return null
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
const LEGACY_SWITCH_STATUS_KEYWORDS = [
|
|
364
|
+
'开关',
|
|
365
|
+
'电源',
|
|
366
|
+
'启停',
|
|
367
|
+
'启动',
|
|
368
|
+
'运行',
|
|
369
|
+
'switch',
|
|
370
|
+
'power'
|
|
371
|
+
]
|
|
372
|
+
|
|
373
|
+
const LEGACY_SWITCH_STATUS_EXCLUDE_KEYWORDS = [
|
|
374
|
+
'模式',
|
|
375
|
+
'温度',
|
|
376
|
+
'风速',
|
|
377
|
+
'设定',
|
|
378
|
+
'设置',
|
|
379
|
+
'锁屏',
|
|
380
|
+
'锁定',
|
|
381
|
+
'lock',
|
|
382
|
+
'mode',
|
|
383
|
+
'temp',
|
|
384
|
+
'speed',
|
|
385
|
+
'set'
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
function isLegacyBinaryInterval(interval) {
|
|
389
|
+
try {
|
|
390
|
+
const payload = typeof interval === 'string' ? JSON.parse(interval) : interval
|
|
391
|
+
return Array.isArray(payload) && Array.isArray(payload[0]) && payload[0].length === 2
|
|
392
|
+
} catch {
|
|
393
|
+
return false
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function isLegacySwitchOperateStatus(source = {}, interval = '') {
|
|
398
|
+
if (source.propType !== 'Operate' || !isLegacyBinaryInterval(interval)) {
|
|
399
|
+
return false
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const normalized = [
|
|
403
|
+
source.propertyKey,
|
|
404
|
+
source.propName,
|
|
405
|
+
source.name,
|
|
406
|
+
source.code,
|
|
407
|
+
source.shortAddress
|
|
408
|
+
].filter(Boolean).join(' ').toLowerCase()
|
|
409
|
+
|
|
410
|
+
if (LEGACY_SWITCH_STATUS_EXCLUDE_KEYWORDS.some(keyword => normalized.includes(keyword))) {
|
|
411
|
+
return false
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return LEGACY_SWITCH_STATUS_KEYWORDS.some(keyword => normalized.includes(keyword))
|
|
415
|
+
}
|
|
416
|
+
|
|
363
417
|
function normalizeLegacyNumber(value) {
|
|
364
418
|
if (value === undefined || value === null || value === '') {
|
|
365
419
|
return null
|
|
@@ -370,15 +424,85 @@ function normalizeLegacyNumber(value) {
|
|
|
370
424
|
return Number.isFinite(num) ? num : null
|
|
371
425
|
}
|
|
372
426
|
|
|
427
|
+
const LEGACY_OPEN_STATUS_KEYWORDS = ['开', '开启', '运行', '启动']
|
|
428
|
+
|
|
429
|
+
function normalizeLegacyStatusText(value) {
|
|
430
|
+
if (value === undefined || value === null) {
|
|
431
|
+
return ''
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (value && typeof value === 'object') {
|
|
435
|
+
return String(value.valueStr ?? value.label ?? value.name ?? value.value ?? '').trim()
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
return String(value).trim()
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function isLegacyOpenStatusText(value) {
|
|
442
|
+
const text = normalizeLegacyStatusText(value)
|
|
443
|
+
if (!text) return false
|
|
444
|
+
|
|
445
|
+
return LEGACY_OPEN_STATUS_KEYWORDS.some(keyword => text.includes(keyword))
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function isLegacyOpenStatusProp(prop = {}) {
|
|
449
|
+
return (
|
|
450
|
+
normalizeLegacyNumber(prop.rawValue) === 1 ||
|
|
451
|
+
normalizeLegacyNumber(prop.value) === 1 ||
|
|
452
|
+
normalizeLegacyNumber(prop.prop?.value) === 1 ||
|
|
453
|
+
isLegacyOpenStatusText(prop.rawValue) ||
|
|
454
|
+
isLegacyOpenStatusText(prop.value) ||
|
|
455
|
+
isLegacyOpenStatusText(prop.valueStr) ||
|
|
456
|
+
isLegacyOpenStatusText(prop.prop?.valueStr)
|
|
457
|
+
)
|
|
458
|
+
}
|
|
459
|
+
|
|
373
460
|
function getLegacyStatusCounts(props = []) {
|
|
374
461
|
const statusProps = props.filter(prop => prop && prop.isStatus)
|
|
375
462
|
return {
|
|
376
463
|
total: statusProps.length,
|
|
377
|
-
open: statusProps.filter(prop =>
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
464
|
+
open: statusProps.filter(prop => isLegacyOpenStatusProp(prop)).length
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function getLegacyOpenStatusProp(props = []) {
|
|
469
|
+
return props.find(prop => prop && prop.isStatus && isLegacyOpenStatusProp(prop))
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function normalizeLegacyStatus(status, props = []) {
|
|
473
|
+
if (!status) {
|
|
474
|
+
return undefined
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const statusCounts = getLegacyStatusCounts(props)
|
|
478
|
+
const openStatusProp = getLegacyOpenStatusProp(props)
|
|
479
|
+
const shouldUseOpenStatus =
|
|
480
|
+
statusCounts.open > 0 &&
|
|
481
|
+
normalizeLegacyNumber(status.value) !== 1 &&
|
|
482
|
+
openStatusProp
|
|
483
|
+
|
|
484
|
+
const displayStatus = shouldUseOpenStatus
|
|
485
|
+
? {
|
|
486
|
+
value: 1,
|
|
487
|
+
label:
|
|
488
|
+
openStatusProp.prop?.valueStr ||
|
|
489
|
+
openStatusProp.valueStr ||
|
|
490
|
+
openStatusProp.name ||
|
|
491
|
+
openStatusProp.propName ||
|
|
492
|
+
'开',
|
|
493
|
+
valueStr:
|
|
494
|
+
openStatusProp.prop?.valueStr ||
|
|
495
|
+
openStatusProp.valueStr ||
|
|
496
|
+
openStatusProp.name ||
|
|
497
|
+
openStatusProp.propName ||
|
|
498
|
+
'开'
|
|
499
|
+
}
|
|
500
|
+
: status
|
|
501
|
+
|
|
502
|
+
return {
|
|
503
|
+
...displayStatus,
|
|
504
|
+
total: status.total ?? statusCounts.total,
|
|
505
|
+
open: status.open ?? statusCounts.open
|
|
382
506
|
}
|
|
383
507
|
}
|
|
384
508
|
|
|
@@ -398,7 +522,7 @@ function normalizeLegacyEasyListProp(source = {}, row = {}) {
|
|
|
398
522
|
const interval = prop.interval || source.interval || source.valueMap || ''
|
|
399
523
|
const line = normalizeLegacyPropLine(source, prop, row)
|
|
400
524
|
const isMain = Boolean(source.isMain)
|
|
401
|
-
const isStatus = Boolean(source.isStatus)
|
|
525
|
+
const isStatus = Boolean(source.isStatus || isLegacySwitchOperateStatus(source, interval))
|
|
402
526
|
const isNumber = Boolean(source.isNumber)
|
|
403
527
|
const isImport = Boolean(source.isImport || isMain || isStatus || isNumber)
|
|
404
528
|
|
|
@@ -448,18 +572,11 @@ function normalizeLegacyEasyListRow(item = {}) {
|
|
|
448
572
|
const props = Array.isArray(row.props)
|
|
449
573
|
? row.props.map(prop => normalizeLegacyEasyListProp(prop, row))
|
|
450
574
|
: []
|
|
451
|
-
const statusCounts = getLegacyStatusCounts(props)
|
|
452
575
|
|
|
453
576
|
return removeUndefinedFields({
|
|
454
577
|
...row,
|
|
455
578
|
props,
|
|
456
|
-
status: row.status
|
|
457
|
-
? {
|
|
458
|
-
...row.status,
|
|
459
|
-
total: row.status.total ?? statusCounts.total,
|
|
460
|
-
open: row.status.open ?? statusCounts.open
|
|
461
|
-
}
|
|
462
|
-
: undefined,
|
|
579
|
+
status: normalizeLegacyStatus(row.status, props),
|
|
463
580
|
lineTime: row.lineTime || props.find(prop => prop.isImport && prop.valueAt)?.valueAt || row.updatedAt || null
|
|
464
581
|
})
|
|
465
582
|
}
|
|
@@ -141,11 +141,26 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
|
|
|
141
141
|
name: '会议室空调',
|
|
142
142
|
line: false,
|
|
143
143
|
status: {
|
|
144
|
-
value:
|
|
145
|
-
label: '
|
|
146
|
-
valueStr: '
|
|
144
|
+
value: 0,
|
|
145
|
+
label: '解锁',
|
|
146
|
+
valueStr: '解锁'
|
|
147
147
|
},
|
|
148
148
|
props: [
|
|
149
|
+
{
|
|
150
|
+
id: 'twin-prop-lock',
|
|
151
|
+
propId: 'device-prop-lock',
|
|
152
|
+
propertyKey: 'lock',
|
|
153
|
+
name: '锁屏',
|
|
154
|
+
isStatus: true,
|
|
155
|
+
line: true,
|
|
156
|
+
value: 0,
|
|
157
|
+
valueStr: '解锁',
|
|
158
|
+
interval: '[["解锁","锁屏"],[0,1]]',
|
|
159
|
+
valueAt: '2026-04-25T06:29:00.000Z',
|
|
160
|
+
prop: {
|
|
161
|
+
id: 'device-prop-lock'
|
|
162
|
+
}
|
|
163
|
+
},
|
|
149
164
|
{
|
|
150
165
|
id: 'twin-prop-mode',
|
|
151
166
|
propId: 'device-prop-mode',
|
|
@@ -153,14 +168,29 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
|
|
|
153
168
|
name: '模式设定',
|
|
154
169
|
isStatus: true,
|
|
155
170
|
line: true,
|
|
156
|
-
value:
|
|
157
|
-
valueStr: '
|
|
171
|
+
value: 0,
|
|
172
|
+
valueStr: '制冷',
|
|
158
173
|
interval: '[["制冷","制热"],[0,1]]',
|
|
159
174
|
valueAt: '2026-04-25T06:30:00.000Z',
|
|
160
175
|
prop: {
|
|
161
176
|
id: 'device-prop-mode'
|
|
162
177
|
}
|
|
163
178
|
},
|
|
179
|
+
{
|
|
180
|
+
id: 'twin-prop-switch',
|
|
181
|
+
propId: 'device-prop-switch',
|
|
182
|
+
propertyKey: 'powerSwitch',
|
|
183
|
+
name: '开关',
|
|
184
|
+
propType: 'Operate',
|
|
185
|
+
line: true,
|
|
186
|
+
value: 1,
|
|
187
|
+
valueStr: '开',
|
|
188
|
+
interval: '[["关","开"],[0,1]]',
|
|
189
|
+
valueAt: '2026-04-25T06:30:30.000Z',
|
|
190
|
+
prop: {
|
|
191
|
+
id: 'device-prop-switch'
|
|
192
|
+
}
|
|
193
|
+
},
|
|
164
194
|
{
|
|
165
195
|
id: 'twin-prop-electric',
|
|
166
196
|
propId: 'device-prop-electric',
|
|
@@ -183,15 +213,16 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
|
|
|
183
213
|
})
|
|
184
214
|
|
|
185
215
|
const row = response.data.rows[0]
|
|
186
|
-
const modeProp = row.props[
|
|
187
|
-
const
|
|
216
|
+
const modeProp = row.props[1]
|
|
217
|
+
const switchProp = row.props[2]
|
|
218
|
+
const electricProp = row.props[3]
|
|
188
219
|
|
|
189
220
|
expect(row._id).toBe('twin-1')
|
|
190
221
|
expect(row.status).toEqual({
|
|
191
222
|
value: 1,
|
|
192
|
-
label: '
|
|
193
|
-
valueStr: '
|
|
194
|
-
total:
|
|
223
|
+
label: '开',
|
|
224
|
+
valueStr: '开',
|
|
225
|
+
total: 3,
|
|
195
226
|
open: 1
|
|
196
227
|
})
|
|
197
228
|
expect(modeProp).toEqual(
|
|
@@ -201,8 +232,8 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
|
|
|
201
232
|
isStatus: true,
|
|
202
233
|
isImport: true,
|
|
203
234
|
line: true,
|
|
204
|
-
value:
|
|
205
|
-
valueStr: '
|
|
235
|
+
value: 0,
|
|
236
|
+
valueStr: '制冷',
|
|
206
237
|
interval: '[["制冷","制热"],[0,1]]',
|
|
207
238
|
valueAt: '2026-04-25T06:30:00.000Z'
|
|
208
239
|
})
|
|
@@ -211,12 +242,21 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
|
|
|
211
242
|
expect.objectContaining({
|
|
212
243
|
_id: 'device-prop-mode',
|
|
213
244
|
line: true,
|
|
214
|
-
value:
|
|
215
|
-
valueStr: '
|
|
245
|
+
value: 0,
|
|
246
|
+
valueStr: '制冷',
|
|
216
247
|
interval: '[["制冷","制热"],[0,1]]',
|
|
217
248
|
valueAt: '2026-04-25T06:30:00.000Z'
|
|
218
249
|
})
|
|
219
250
|
)
|
|
251
|
+
expect(switchProp).toEqual(
|
|
252
|
+
expect.objectContaining({
|
|
253
|
+
propType: 'Operate',
|
|
254
|
+
isStatus: true,
|
|
255
|
+
isImport: true,
|
|
256
|
+
value: 1,
|
|
257
|
+
valueStr: '开'
|
|
258
|
+
})
|
|
259
|
+
)
|
|
220
260
|
expect(electricProp).toEqual(
|
|
221
261
|
expect.objectContaining({
|
|
222
262
|
isMain: true,
|