@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.
Files changed (40) hide show
  1. package/README.md +9 -0
  2. package/dist/index.d.ts +0 -0
  3. package/dist/index.js +0 -0
  4. package/dist/resources/i18n.d.ts +55 -0
  5. package/dist/resources/i18n.js +212 -0
  6. package/dist/service/specs/error-code.d.ts +19 -0
  7. package/dist/service/specs/error-code.js +41 -0
  8. package/dist/service/specs/index.d.ts +95 -0
  9. package/dist/service/specs/index.js +412 -0
  10. package/dist/service/specs/spec.d.ts +10 -0
  11. package/dist/service/specs/spec.js +109 -0
  12. package/dist/service/specs/specCache.d.ts +85 -0
  13. package/dist/service/specs/specCache.js +421 -0
  14. package/dist/service/specs/std-spec.d.ts +5 -0
  15. package/dist/service/specs/std-spec.js +228 -0
  16. package/dist/service/specs/subject.d.ts +20 -0
  17. package/dist/service/specs/subject.js +145 -0
  18. package/dist/service/specs/utils.d.ts +28 -0
  19. package/dist/service/specs/utils.js +46 -0
  20. package/dist/specs/i18n-parser.d.ts +10 -0
  21. package/dist/specs/i18n-parser.js +300 -0
  22. package/dist/specs/instance-parser.d.ts +26 -0
  23. package/dist/specs/instance-parser.js +706 -0
  24. package/dist/store/useGlobalSpecManager.d.ts +320 -0
  25. package/dist/store/useGlobalSpecManager.js +867 -0
  26. package/dist/types/index.d.ts +23 -0
  27. package/dist/types/index.js +1 -0
  28. package/dist/utils/fns.d.ts +12 -0
  29. package/dist/utils/fns.js +308 -0
  30. package/dist/utils/get-value-or-default.d.ts +1 -0
  31. package/dist/utils/get-value-or-default.js +4 -0
  32. package/dist/utils/i18n.d.ts +1 -0
  33. package/dist/utils/i18n.js +141 -0
  34. package/dist/utils/objects.d.ts +2 -0
  35. package/dist/utils/objects.js +222 -0
  36. package/dist/utils/spec.d.ts +8 -0
  37. package/dist/utils/spec.js +171 -0
  38. package/dist/utils/types.d.ts +3 -0
  39. package/dist/utils/types.js +25 -0
  40. package/package.json +27 -0
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Spec数据缓存管理器
3
+ *
4
+ * 功能说明:
5
+ * 1. 内存缓存:使用Map存储,提供快速读写
6
+ * 2. 持久化缓存:使用Host.storage,支持数据持久化
7
+ * 3. 批量持久化:减少storage写操作频率
8
+ * 4. 冲突解决:处理缓存数据与实时数据的冲突
9
+ * 5. 数据来源标识:区分缓存数据和实时数据的来源
10
+ *
11
+ * 缓存策略:
12
+ * - 内存缓存优先,减少storage访问
13
+ * - 批量持久化,最小持久化间隔
14
+ * - 缓存更新条件:值变化或时间戳更新
15
+ * - 数据来源标识:__cache_source__字段标识数据来源
16
+ */
17
+
18
+ import { Host, Service, Device } from 'miot';
19
+ import { encodeProp } from "../../utils/spec";
20
+ import { deepEqual } from "../../utils/objects";
21
+ import { OK } from "./error-code";
22
+ // 缓存配置
23
+ const CACHE_CONFIG = {
24
+ // 持久化间隔(毫秒)
25
+ PERSIST_INTERVAL: 2000,
26
+ // 存储键名
27
+ STORAGE_KEY: `${Service.account.ID}_${Device.deviceID}_spec_cache`
28
+ };
29
+ // 数据来源类型
30
+ export const CACHE_SOURCE = {
31
+ CACHE: 'cache',
32
+ // 从缓存读取
33
+ GET: 'get',
34
+ // 通过get方法获取
35
+ SET: 'set',
36
+ // 通过set方法设置
37
+ SUBSCRIBE: 'subscribe',
38
+ // 通过subscribe订阅
39
+ ACTION: 'action' // 通过action调用
40
+ };
41
+
42
+ /**
43
+ * 缓存数据结构
44
+ * @typedef {Object} CacheItem
45
+ * @property {*} value - 属性值
46
+ * @property {number} updateTime - 更新时间戳(秒)
47
+ * @property {string} specDataSource - 数据来源(CACHE_SOURCE枚举)
48
+ * @property {number} timestamp - 缓存时间戳(毫秒)
49
+ */
50
+
51
+ class SpecCache {
52
+ constructor() {
53
+ // 内存缓存:Map<key, CacheItem>
54
+ this.memoryCache = new Map();
55
+
56
+ // 持久化队列:Set<key>,待持久化的key集合
57
+ this.persistQueue = new Set();
58
+
59
+ // 最后持久化时间
60
+ this.lastPersistTime = 0;
61
+
62
+ // 持久化定时器
63
+ this.persistTimer = null;
64
+
65
+ // 是否已加载持久化数据
66
+ this.loaded = false;
67
+
68
+ // 批量持久化锁
69
+ this.persisting = false;
70
+ }
71
+
72
+ /**
73
+ * 初始化缓存,加载持久化数据
74
+ * @returns {Promise<void>}
75
+ */
76
+ init() {
77
+ if (this.loaded) {
78
+ return Promise.resolve(this.memoryCache);
79
+ }
80
+ return new Promise((resolve, reject) => {
81
+ this.loadFromStorage().then(() => {
82
+ resolve(this.memoryCache);
83
+ }).catch(error => {
84
+ reject(error);
85
+ });
86
+ });
87
+ }
88
+
89
+ /**
90
+ * 从持久化存储加载缓存
91
+ * @returns {Promise<void>}
92
+ */
93
+ loadFromStorage() {
94
+ return new Promise((resolve, reject) => {
95
+ Host.storage.get(CACHE_CONFIG.STORAGE_KEY).then(data => {
96
+ console.log('[SpecCache] Load from storage:', data);
97
+ if (data && typeof data === 'object') {
98
+ let validCount = 0;
99
+ Object.entries(data).forEach(([key, item]) => {
100
+ // 标记为缓存来源
101
+ this.memoryCache.set(key, {
102
+ ...item,
103
+ specDataSource: CACHE_SOURCE.CACHE,
104
+ fromStorage: true
105
+ });
106
+ validCount++;
107
+ });
108
+ console.log(`[SpecCache] Loaded ${validCount} items from storage`);
109
+ }
110
+ this.loaded = true;
111
+ resolve(this.memoryCache);
112
+ }).catch(error => {
113
+ console.error('[SpecCache] Load error:', error);
114
+ this.loaded = true;
115
+ reject(error);
116
+ });
117
+ });
118
+ }
119
+
120
+ /**
121
+ * 获取缓存数据
122
+ * @param {string} key - 缓存键
123
+ * @returns {CacheItem|null} 缓存项或null
124
+ */
125
+ get(key) {
126
+ const item = this.memoryCache.get(key);
127
+ if (!item) {
128
+ return null;
129
+ }
130
+ return {
131
+ ...item
132
+ };
133
+ }
134
+
135
+ /**
136
+ * 设置缓存数据
137
+ * @param {string} key - 缓存键
138
+ * @param {*} value - 值
139
+ * @param {number} updateTime - 更新时间戳(秒)
140
+ * @param {string} specDataSource - 数据来源
141
+ * @returns {boolean} 是否发生变化
142
+ */
143
+ put(key, value, updateTime, specDataSource = CACHE_SOURCE.GET) {
144
+ const now = Date.now();
145
+ const existing = this.memoryCache.get(key);
146
+
147
+ // 检查是否需要更新
148
+ const needUpdate = this.shouldUpdate(existing, value, updateTime);
149
+ if (needUpdate) {
150
+ const item = {
151
+ value,
152
+ updateTime: updateTime || Math.floor(now / 1000),
153
+ specDataSource,
154
+ fromCache: false,
155
+ timestamp: now
156
+ };
157
+ this.memoryCache.set(key, item);
158
+ this.addToPersistQueue(key);
159
+ return true;
160
+ }
161
+ return false;
162
+ }
163
+
164
+ /**
165
+ * 判断是否需要更新缓存
166
+ * @param {CacheItem} existing - 现有缓存
167
+ * @param {*} newValue - 新值
168
+ * @param {number} newUpdateTime - 新时间戳
169
+ * @returns {boolean} 是否需要更新
170
+ */
171
+ shouldUpdate(existing, newValue, newUpdateTime) {
172
+ if (!existing) {
173
+ return true; // 无缓存,需要更新
174
+ }
175
+
176
+ // 值发生变化
177
+ if (!deepEqual(existing.value, newValue)) {
178
+ return true;
179
+ }
180
+
181
+ // 时间戳更新(严格大于)
182
+ if (newUpdateTime && existing.updateTime && newUpdateTime >= existing.updateTime) {
183
+ return true;
184
+ }
185
+ return false;
186
+ }
187
+
188
+ /**
189
+ * 添加到持久化队列
190
+ * @param {string} key - 缓存键
191
+ */
192
+ addToPersistQueue(key) {
193
+ this.persistQueue.add(key);
194
+ this.schedulePersist();
195
+ }
196
+
197
+ /**
198
+ * 安排持久化任务
199
+ */
200
+ schedulePersist() {
201
+ // 如果已有定时器或正在持久化,不重复调度
202
+ if (this.persistTimer || this.persisting) {
203
+ return;
204
+ }
205
+ const now = Date.now();
206
+ const timeSinceLastPersist = now - this.lastPersistTime;
207
+
208
+ // 如果距离上次持久化已超过间隔,立即执行
209
+ if (timeSinceLastPersist >= CACHE_CONFIG.PERSIST_INTERVAL) {
210
+ this.doPersist();
211
+ return;
212
+ }
213
+
214
+ // 否则调度到间隔后执行
215
+ const delay = CACHE_CONFIG.PERSIST_INTERVAL - timeSinceLastPersist;
216
+ this.persistTimer = setTimeout(() => {
217
+ this.persistTimer = null;
218
+ this.doPersist();
219
+ }, delay);
220
+ }
221
+
222
+ /**
223
+ * 执行持久化
224
+ * @returns {Promise<void>}
225
+ */
226
+ async doPersist() {
227
+ if (this.persisting || this.persistQueue.size === 0) {
228
+ return;
229
+ }
230
+ this.persisting = true;
231
+ try {
232
+ // 准备持久化数据
233
+ const dataToPersist = {};
234
+ const keysToPersist = Array.from(this.persistQueue);
235
+ for (const key of keysToPersist) {
236
+ const item = this.memoryCache.get(key);
237
+ if (item) {
238
+ dataToPersist[key] = {
239
+ value: item.value,
240
+ updateTime: item.updateTime,
241
+ timestamp: item.timestamp
242
+ };
243
+ }
244
+ }
245
+ console.log('[SpecCache] Persist data:', dataToPersist);
246
+
247
+ // 合并已有存储,避免未变更 key 被覆盖
248
+ let mergedData = {};
249
+ try {
250
+ const existingData = await Host.storage.get(CACHE_CONFIG.STORAGE_KEY);
251
+ if (existingData && typeof existingData === 'object') {
252
+ mergedData = {
253
+ ...existingData
254
+ };
255
+ }
256
+ } catch (error) {
257
+ console.warn('[SpecCache] Read storage before persist failed:', error);
258
+ }
259
+ mergedData = {
260
+ ...mergedData,
261
+ ...dataToPersist
262
+ };
263
+
264
+ // 执行持久化
265
+ await Host.storage.set(CACHE_CONFIG.STORAGE_KEY, mergedData);
266
+
267
+ // 清除已持久化的key
268
+ keysToPersist.forEach(key => this.persistQueue.delete(key));
269
+ this.lastPersistTime = Date.now();
270
+ console.log(`[SpecCache] Persisted ${keysToPersist.length} items`);
271
+ } catch (error) {
272
+ console.error('[SpecCache] Persist error:', error);
273
+ } finally {
274
+ this.persisting = false;
275
+
276
+ // 如果队列中还有数据,继续调度
277
+ if (this.persistQueue.size > 0) {
278
+ this.schedulePersist();
279
+ }
280
+ }
281
+ }
282
+
283
+ /**
284
+ * 立即持久化所有数据
285
+ * @returns {Promise<void>}
286
+ */
287
+ async flush() {
288
+ if (this.persistTimer) {
289
+ clearTimeout(this.persistTimer);
290
+ this.persistTimer = null;
291
+ }
292
+ await this.doPersist();
293
+ }
294
+
295
+ /**
296
+ * 清理最旧的缓存项
297
+ */
298
+ cleanupOldest() {
299
+ // 已移除内存上限限制,保留占位以兼容调用方
300
+ }
301
+
302
+ /**
303
+ * 清除指定key的缓存
304
+ * @param {string} key - 缓存键
305
+ */
306
+ remove(key) {
307
+ this.memoryCache.delete(key);
308
+ this.persistQueue.delete(key);
309
+ }
310
+
311
+ /**
312
+ * 清空所有缓存
313
+ * @param {boolean} clearStorage - 是否同时清除持久化数据
314
+ * @returns {Promise<void>}
315
+ */
316
+ async clear(clearStorage = false) {
317
+ this.memoryCache.clear();
318
+ this.persistQueue.clear();
319
+ if (this.persistTimer) {
320
+ clearTimeout(this.persistTimer);
321
+ this.persistTimer = null;
322
+ }
323
+ if (clearStorage) {
324
+ try {
325
+ await Host.storage.set(CACHE_CONFIG.STORAGE_KEY, {});
326
+ } catch (error) {
327
+ console.error('[SpecCache] Clear storage error:', error);
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * 获取缓存统计信息
334
+ * @returns {Object} 统计信息
335
+ */
336
+ getStats() {
337
+ const sourceCount = {};
338
+ for (const item of this.memoryCache.values()) {
339
+ const specDataSource = item.specDataSource || 'unknown';
340
+ sourceCount[specDataSource] = (sourceCount[specDataSource] || 0) + 1;
341
+ }
342
+ return {
343
+ memorySize: this.memoryCache.size,
344
+ persistQueueSize: this.persistQueue.size,
345
+ sourceCount,
346
+ lastPersistTime: this.lastPersistTime,
347
+ persisting: this.persisting
348
+ };
349
+ }
350
+
351
+ /**
352
+ * 生成缓存键
353
+ * @param {Object} prop - 属性对象
354
+ * @returns {string} 缓存键
355
+ */
356
+ getCacheKey(prop) {
357
+ if (!prop) return '';
358
+ return encodeProp(prop);
359
+ }
360
+
361
+ /**
362
+ * 获取缓存中的属性值(不触发源请求)
363
+ * @param {Array} props - 属性列表
364
+ * @returns {Array} 缓存结果
365
+ */
366
+ getCachedProps(props) {
367
+ const validProps = (props || []).filter(p => p && p.siid !== undefined && p.piid !== undefined);
368
+ return validProps.map(prop => {
369
+ const key = this.getCacheKey(prop);
370
+ const cached = this.get(key);
371
+ if (cached) {
372
+ return {
373
+ ...prop,
374
+ value: cached.value,
375
+ updateTime: cached.updateTime,
376
+ code: OK,
377
+ specDataSource: cached.specDataSource
378
+ };
379
+ }
380
+ return {
381
+ ...prop,
382
+ code: OK
383
+ };
384
+ });
385
+ }
386
+
387
+ /**
388
+ * 设置缓存中的属性值(不触发源请求)
389
+ * @param {Array} props - 属性列表
390
+ * @returns {Promise<Array>} 设置结果
391
+ */
392
+ setCachedProps(props) {
393
+ const validProps = (props || []).filter(p => p && p.siid !== undefined && p.piid !== undefined && p.value !== undefined);
394
+ validProps.forEach(prop => {
395
+ const key = this.getCacheKey(prop);
396
+ this.put(key, prop.value, Math.floor(Date.now() / 1000), CACHE_SOURCE.SET);
397
+ });
398
+ return Promise.resolve(validProps.map(p => ({
399
+ ...p,
400
+ code: OK
401
+ })));
402
+ }
403
+
404
+ /**
405
+ * 执行动作(缓存处理)
406
+ * @param {Object} prop - 动作参数
407
+ * @returns {Promise<Object>} 执行结果
408
+ */
409
+ doAction(prop) {
410
+ // 动作执行后可能需要更新相关属性缓存
411
+ // 这里可以添加具体的业务逻辑
412
+ return Promise.resolve({
413
+ ...prop,
414
+ code: 0 // OK
415
+ });
416
+ }
417
+ }
418
+
419
+ // 单例实例
420
+ const instance = new SpecCache();
421
+ export default instance;
@@ -0,0 +1,5 @@
1
+ import { Spec } from '../../types';
2
+ export declare function getProps(props: Spec[], chunkFn?: (data: any) => void): Promise<any[]>;
3
+ export declare function setProps(props: Spec[]): Promise<any>;
4
+ export declare function doAction(prop: Spec): Promise<any>;
5
+ export declare function subscribe(props: Spec[], listener: any): any;
@@ -0,0 +1,228 @@
1
+ import { Device, DeviceEvent, Service } from 'miot';
2
+ import Subject from "./subject";
3
+ import { genError, getEventGenerator, mapError } from "./utils";
4
+ import { isTypeOf } from "../../utils/types";
5
+ import { encodeProp, decodeProp, specsToSubscribeKeys, specAccess } from "../../utils/spec";
6
+ import { OK } from "./error-code";
7
+ const specSubject = new Subject(getEventGenerator('std_spec_subject', encodeProp));
8
+ let receivedMessagesSubscription = null;
9
+ export function getProps(props, chunkFn) {
10
+ // console.log('getProps---props', props);
11
+ // 处理固件不上报的情况,此时须将dataSource 设置为2,强行从固件读取
12
+ const ps = (props || []).reduce((ret, prop) => {
13
+ if (specAccess(prop, 'read')) {
14
+ const {
15
+ miid,
16
+ siid,
17
+ piid,
18
+ did = Device.deviceID,
19
+ dataSource = prop.fromSource ? 1 : 2
20
+ } = prop;
21
+ const p = {
22
+ siid,
23
+ piid,
24
+ did
25
+ };
26
+ if (miid && !isNaN(parseInt(miid, 10))) {
27
+ p.miid = miid;
28
+ }
29
+ if (!ret[dataSource]) {
30
+ ret[dataSource] = [];
31
+ }
32
+ ret[dataSource].push(p);
33
+ }
34
+ return ret;
35
+ }, {});
36
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - get) start: ]${JSON.stringify({
37
+ ps
38
+ })}`);
39
+ return Promise.all(Object.entries(ps).map(([dataSource, v]) => {
40
+ return Service.spec.getPropertiesValue(v, parseInt(dataSource, 10)).then(res => {
41
+ isTypeOf('Function', chunkFn) && chunkFn && chunkFn(res);
42
+ return res;
43
+ }).catch(reason => {
44
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - get) error: ]${JSON.stringify({
45
+ v,
46
+ dataSource,
47
+ reason
48
+ })}`);
49
+ mapError(props)(reason);
50
+ }).finally(() => {});
51
+ })).then(res => {
52
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - get) res: ]${JSON.stringify({
53
+ res
54
+ })}`);
55
+ return res.flat();
56
+ });
57
+ }
58
+ export function setProps(props) {
59
+ props = fillInfo(props);
60
+ console.log('std-spec---setProps', props, 'time', Math.floor(Date.now() / 1000));
61
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - set) start: ]${JSON.stringify({
62
+ props
63
+ })}`);
64
+ return Service.spec.setPropertiesValue(props.filter(prop => {
65
+ return !!prop;
66
+ }).map(prop => {
67
+ const t = {
68
+ did: prop.did,
69
+ siid: prop.siid,
70
+ piid: prop.piid,
71
+ value: prop.value
72
+ };
73
+ if (prop.miid) {
74
+ t.miid = prop.miid;
75
+ }
76
+ return t;
77
+ })).then(res => {
78
+ console.log('std-spec---setProps-res', res, 'time', Math.floor(Date.now() / 1000));
79
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - set) res: ]${JSON.stringify({
80
+ res
81
+ })}`);
82
+ return res;
83
+ }).catch(reason => {
84
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - set) error: ]${JSON.stringify({
85
+ props
86
+ })}`);
87
+ mapError(props)(reason);
88
+ });
89
+ }
90
+ export function doAction(prop) {
91
+ const action = {
92
+ ...prop,
93
+ did: prop.did ? prop.did : Device.deviceID
94
+ };
95
+ const t = {
96
+ did: action.did,
97
+ siid: action.siid,
98
+ aiid: action.aiid,
99
+ in: action.in
100
+ };
101
+ if (action.miid) {
102
+ t.miid = action.miid;
103
+ }
104
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - action) start: ]${JSON.stringify({
105
+ t
106
+ })}`);
107
+ return Service.spec.doAction(t).then(res => {
108
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - action) res: ]${JSON.stringify({
109
+ res
110
+ })}`);
111
+ return {
112
+ ...action,
113
+ ...res
114
+ };
115
+ }).catch(reason => {
116
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.spec, ${new Date()}, doSpecOperation (std channel - action) error: ]${JSON.stringify({
117
+ reason
118
+ })}`);
119
+ genError(action)(reason);
120
+ });
121
+ }
122
+ function subscribeReceivedMessage() {
123
+ const deviceReceivedMessages = DeviceEvent.deviceReceivedMessages;
124
+ return deviceReceivedMessages.addListener((device, messages, data) => {
125
+ if (!device || device.deviceID !== Device.deviceID || !messages) {
126
+ return;
127
+ }
128
+ // console.log('miot.plugin.car-DeviceEvent.deviceReceivedMessages', messages);
129
+
130
+ Service.smarthome.reportLog(Device.model, `[miot.plugin.car, ${new Date()}, data-source::std-spec::subscribeReceivedMessage:]${JSON.stringify({
131
+ messages,
132
+ data
133
+ })}`);
134
+ const did = device.deviceID;
135
+ messages.forEach((v, k) => {
136
+ const prop = decodeProp(k);
137
+ const d = (data || []).find(({
138
+ key
139
+ }) => k === key);
140
+ if (!prop || !d) {
141
+ return;
142
+ }
143
+ const updateTime = d.time;
144
+ // prop
145
+ if (prop.piid) {
146
+ // const k = toKey(prop);
147
+ // // 如果本地spec值更新(本地的updateTime严格大于收到的updateTime,因为这里是秒级,不能包含等于),则不处理
148
+ // let { updateTime: updateTimeFromCache = 0 } = cache.get(k);
149
+ // if (updateTimeFromCache > updateTime) {
150
+ // return;
151
+ // }
152
+ specSubject.publish({
153
+ ...prop,
154
+ value: Array.isArray(v) ? v[0] : v,
155
+ code: OK,
156
+ updateTime,
157
+ did
158
+ }, false);
159
+ return;
160
+ }
161
+ // event
162
+ if (prop.eiid) {
163
+ // 有关联属性
164
+ // 把event 本身更新一次
165
+ // 如果只有一个返回值,取第0个value
166
+ // 如果有多个返回值,返回value 数组
167
+ let parsedValue = v;
168
+ if (Array.isArray(v)) {
169
+ parsedValue = v.map(v1 => {
170
+ return isTypeOf('Object', v1) && v1.piid ? v1.value : v1;
171
+ });
172
+ parsedValue = parsedValue.length === 1 ? parsedValue[0] : parsedValue;
173
+ }
174
+ specSubject.publish({
175
+ ...prop,
176
+ fromEvent: true,
177
+ value: parsedValue,
178
+ code: OK,
179
+ updateTime,
180
+ did
181
+ }, false);
182
+ }
183
+ });
184
+ });
185
+ }
186
+ function fillInfo(props) {
187
+ const propsNew = props.filter(element => {
188
+ return element !== null;
189
+ });
190
+ return propsNew.map(prop => {
191
+ const {
192
+ did,
193
+ miid,
194
+ ...rest
195
+ } = prop;
196
+ const t = {
197
+ ...rest,
198
+ did: did || Device.deviceID
199
+ };
200
+ if (miid) {
201
+ t.miid = miid;
202
+ }
203
+ return t;
204
+ });
205
+ }
206
+ export function subscribe(props, listener) {
207
+ if (!receivedMessagesSubscription) {
208
+ receivedMessagesSubscription = subscribeReceivedMessage();
209
+ }
210
+ props = fillInfo(props);
211
+ const keys = specsToSubscribeKeys(props);
212
+ // return Device.getDeviceWifi().subscribeMessages(...keys).then(() => {
213
+ return Device.getDeviceWifi().listenMessages(...keys).then(() => {
214
+ const subscription = specSubject.subscribe(props, listener);
215
+ const subscribed = props.map(prop => {
216
+ return {
217
+ ...prop,
218
+ code: OK
219
+ };
220
+ });
221
+ return {
222
+ props: subscribed,
223
+ unsubscribe: () => {
224
+ subscription && subscription.unsubscribe && subscription.unsubscribe();
225
+ }
226
+ };
227
+ }).catch(mapError(props));
228
+ }
@@ -0,0 +1,20 @@
1
+ export default class Subject<T> {
2
+ keyOf: (topic: T) => string;
3
+ subscriptions: Set<any>;
4
+ handler: any;
5
+ filter: any;
6
+ constructor(keyOf: (topic: T) => string, handler?: any);
7
+ setFilter(filter: any): void;
8
+ subscribe(topics: T[], listener: any): {
9
+ unsubscribe: () => void;
10
+ isActive: () => boolean;
11
+ topics: T[];
12
+ };
13
+ getAllTopics(): T[];
14
+ publish(topic: T, active: boolean, callback?: (topic: T) => void): void;
15
+ unsubscribeAll(): void;
16
+ }
17
+ export declare function newSimpleFilter(): {
18
+ accept: (key: string, topic: any) => boolean;
19
+ reset: () => void;
20
+ };