nayota-show-sdk 1.3.74 → 1.3.76

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nayota-show-sdk",
3
- "version": "1.3.74",
3
+ "version": "1.3.76",
4
4
  "description": "nayota-show-server rest-api",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -215,12 +215,16 @@ function mapIotDepartsToLegacy(item = {}) {
215
215
  }
216
216
 
217
217
  function mapDevicesToIotQuery(query = {}) {
218
+ const digitalTwinTypeId = query.digitalTwinTypeId != null && query.digitalTwinTypeId !== ''
219
+ ? query.digitalTwinTypeId
220
+ : resolveLegacyReference(query.deviceClass) || undefined
221
+
218
222
  return removeUndefinedFields({
219
223
  ...omitKeys(query, ['_id', 'depart', 'area', 'deviceClass', 'cloudType', 'status', 'sort']),
220
224
  id: query.id || query._id,
221
225
  hierarchyId: query.hierarchyId || query.depart,
222
226
  spaceId: query.spaceId || query.area,
223
- digitalTwinTypeId: query.digitalTwinTypeId || resolveLegacyReference(query.deviceClass),
227
+ digitalTwinTypeId,
224
228
  isActive: query.isActive != null ? query.isActive : (query.cloudType != null ? query.cloudType : query.status),
225
229
  ...parseLegacySort(query.sort, {
226
230
  deviceClass: 'digitalTwinTypeId',
@@ -232,6 +236,10 @@ function mapDevicesToIotQuery(query = {}) {
232
236
  }
233
237
 
234
238
  function mapDevicesToIotBody(data = {}) {
239
+ const digitalTwinTypeId = data.digitalTwinTypeId != null && data.digitalTwinTypeId !== ''
240
+ ? data.digitalTwinTypeId
241
+ : resolveLegacyReference(data.deviceClass) || undefined
242
+
235
243
  const metadata = mergeMetadata(data.metadata, {
236
244
  configDeviceId: data.n_device,
237
245
  mapLatLng: data.mapLatLng,
@@ -268,7 +276,7 @@ function mapDevicesToIotBody(data = {}) {
268
276
  twinId: data.twinId || data.n_device || fallbackCode(data.name || data._id, 'TWIN'),
269
277
  hierarchyId: data.hierarchyId || data.depart,
270
278
  spaceId: data.spaceId || data.area,
271
- digitalTwinTypeId: data.digitalTwinTypeId || resolveLegacyReference(data.deviceClass),
279
+ digitalTwinTypeId,
272
280
  isActive: data.isActive != null ? data.isActive : (data.cloudType != null ? data.cloudType : data.status),
273
281
  metadata: Object.keys(metadata).length ? metadata : undefined
274
282
  })
@@ -360,6 +368,60 @@ function normalizeLegacyPropLine(source = {}, prop = {}, row = {}) {
360
368
  return null
361
369
  }
362
370
 
371
+ const LEGACY_SWITCH_STATUS_KEYWORDS = [
372
+ '开关',
373
+ '电源',
374
+ '启停',
375
+ '启动',
376
+ '运行',
377
+ 'switch',
378
+ 'power'
379
+ ]
380
+
381
+ const LEGACY_SWITCH_STATUS_EXCLUDE_KEYWORDS = [
382
+ '模式',
383
+ '温度',
384
+ '风速',
385
+ '设定',
386
+ '设置',
387
+ '锁屏',
388
+ '锁定',
389
+ 'lock',
390
+ 'mode',
391
+ 'temp',
392
+ 'speed',
393
+ 'set'
394
+ ]
395
+
396
+ function isLegacyBinaryInterval(interval) {
397
+ try {
398
+ const payload = typeof interval === 'string' ? JSON.parse(interval) : interval
399
+ return Array.isArray(payload) && Array.isArray(payload[0]) && payload[0].length === 2
400
+ } catch {
401
+ return false
402
+ }
403
+ }
404
+
405
+ function isLegacySwitchOperateStatus(source = {}, interval = '') {
406
+ if (source.propType !== 'Operate' || !isLegacyBinaryInterval(interval)) {
407
+ return false
408
+ }
409
+
410
+ const normalized = [
411
+ source.propertyKey,
412
+ source.propName,
413
+ source.name,
414
+ source.code,
415
+ source.shortAddress
416
+ ].filter(Boolean).join(' ').toLowerCase()
417
+
418
+ if (LEGACY_SWITCH_STATUS_EXCLUDE_KEYWORDS.some(keyword => normalized.includes(keyword))) {
419
+ return false
420
+ }
421
+
422
+ return LEGACY_SWITCH_STATUS_KEYWORDS.some(keyword => normalized.includes(keyword))
423
+ }
424
+
363
425
  function normalizeLegacyNumber(value) {
364
426
  if (value === undefined || value === null || value === '') {
365
427
  return null
@@ -468,7 +530,7 @@ function normalizeLegacyEasyListProp(source = {}, row = {}) {
468
530
  const interval = prop.interval || source.interval || source.valueMap || ''
469
531
  const line = normalizeLegacyPropLine(source, prop, row)
470
532
  const isMain = Boolean(source.isMain)
471
- const isStatus = Boolean(source.isStatus)
533
+ const isStatus = Boolean(source.isStatus || isLegacySwitchOperateStatus(source, interval))
472
534
  const isNumber = Boolean(source.isNumber)
473
535
  const isImport = Boolean(source.isImport || isMain || isStatus || isNumber)
474
536
 
@@ -127,6 +127,25 @@ describe('iotModuleSpecs departs hierarchy compatibility', () => {
127
127
  })
128
128
  })
129
129
 
130
+ describe('iotModuleSpecs devices write compatibility', () => {
131
+ const devices = iotModuleSpecs.devices.operations
132
+
133
+ test('does not send digitalTwinTypeId null for partial map coordinate updates', () => {
134
+ const request = devices.updateOne.toRequest({
135
+ _id: '77b8889e-7d3a-4efa-9fc9-858305468d6c',
136
+ digitalTwinTypeId: null,
137
+ spaceId: 'c13c121f-1a23-4656-be54-9e7488f43c55',
138
+ svgCoordinates: [891.4283167347667, 739.999788571489]
139
+ })
140
+
141
+ expect(request.url).toBe('/digital-twins/77b8889e-7d3a-4efa-9fc9-858305468d6c')
142
+ expect(request.method).toBe('patch')
143
+ expect(request.data.digitalTwinTypeId).toBeUndefined()
144
+ expect(request.data.spaceId).toBe('c13c121f-1a23-4656-be54-9e7488f43c55')
145
+ expect(request.data.svgCoordinates).toEqual([891.4283167347667, 739.999788571489])
146
+ })
147
+ })
148
+
130
149
  describe('iotModuleSpecs devices easyList legacy compatibility', () => {
131
150
  const easyList = iotModuleSpecs.devices.operations.easyList
132
151
 
@@ -168,14 +187,29 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
168
187
  name: '模式设定',
169
188
  isStatus: true,
170
189
  line: true,
171
- value: 1,
172
- valueStr: '制热',
190
+ value: 0,
191
+ valueStr: '制冷',
173
192
  interval: '[["制冷","制热"],[0,1]]',
174
193
  valueAt: '2026-04-25T06:30:00.000Z',
175
194
  prop: {
176
195
  id: 'device-prop-mode'
177
196
  }
178
197
  },
198
+ {
199
+ id: 'twin-prop-switch',
200
+ propId: 'device-prop-switch',
201
+ propertyKey: 'powerSwitch',
202
+ name: '开关',
203
+ propType: 'Operate',
204
+ line: true,
205
+ value: 1,
206
+ valueStr: '开',
207
+ interval: '[["关","开"],[0,1]]',
208
+ valueAt: '2026-04-25T06:30:30.000Z',
209
+ prop: {
210
+ id: 'device-prop-switch'
211
+ }
212
+ },
179
213
  {
180
214
  id: 'twin-prop-electric',
181
215
  propId: 'device-prop-electric',
@@ -199,14 +233,15 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
199
233
 
200
234
  const row = response.data.rows[0]
201
235
  const modeProp = row.props[1]
202
- const electricProp = row.props[2]
236
+ const switchProp = row.props[2]
237
+ const electricProp = row.props[3]
203
238
 
204
239
  expect(row._id).toBe('twin-1')
205
240
  expect(row.status).toEqual({
206
241
  value: 1,
207
- label: '制热',
208
- valueStr: '制热',
209
- total: 2,
242
+ label: '',
243
+ valueStr: '',
244
+ total: 3,
210
245
  open: 1
211
246
  })
212
247
  expect(modeProp).toEqual(
@@ -216,8 +251,8 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
216
251
  isStatus: true,
217
252
  isImport: true,
218
253
  line: true,
219
- value: 1,
220
- valueStr: '制热',
254
+ value: 0,
255
+ valueStr: '制冷',
221
256
  interval: '[["制冷","制热"],[0,1]]',
222
257
  valueAt: '2026-04-25T06:30:00.000Z'
223
258
  })
@@ -226,12 +261,21 @@ describe('iotModuleSpecs devices easyList legacy compatibility', () => {
226
261
  expect.objectContaining({
227
262
  _id: 'device-prop-mode',
228
263
  line: true,
229
- value: 1,
230
- valueStr: '制热',
264
+ value: 0,
265
+ valueStr: '制冷',
231
266
  interval: '[["制冷","制热"],[0,1]]',
232
267
  valueAt: '2026-04-25T06:30:00.000Z'
233
268
  })
234
269
  )
270
+ expect(switchProp).toEqual(
271
+ expect.objectContaining({
272
+ propType: 'Operate',
273
+ isStatus: true,
274
+ isImport: true,
275
+ value: 1,
276
+ valueStr: '开'
277
+ })
278
+ )
235
279
  expect(electricProp).toEqual(
236
280
  expect.objectContaining({
237
281
  isMain: true,