@flexem/fc-gui 3.0.0-alpha.168 → 3.0.0-alpha.169
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/bundles/@flexem/fc-gui.umd.js +113 -37
- package/bundles/@flexem/fc-gui.umd.js.map +1 -1
- package/bundles/@flexem/fc-gui.umd.min.js +4 -4
- package/bundles/@flexem/fc-gui.umd.min.js.map +1 -1
- package/communication/variable/variable-communicator.d.ts +1 -0
- package/elements/per-view-variable-communicator.d.ts +1 -0
- package/elements/per-view-variable-communicator.js +6 -0
- package/elements/per-view-variable-communicator.metadata.json +1 -1
- package/elements/scroll-alarm/scroll-alarm-element.d.ts +5 -1
- package/elements/scroll-alarm/scroll-alarm-element.js +97 -37
- package/elements/scroll-alarm/scroll-alarm-element.metadata.json +1 -1
- package/package.json +1 -1
- package/remote/communication/variable/remote-variable-communicator.d.ts +1 -0
- package/remote/communication/variable/remote-variable-communicator.js +10 -0
- package/remote/communication/variable/remote-variable-communicator.metadata.json +1 -1
- package/remote/communication/variable/remote-variable-protocol.d.ts +3 -0
|
@@ -10,6 +10,7 @@ export interface VariableCommunicator {
|
|
|
10
10
|
subscribeVariableState(variableName: string): Observable<VariableState>;
|
|
11
11
|
subscribeVariableStates(variableNames: Array<string>): Observable<Array<VariableState>>;
|
|
12
12
|
subscribeUserDeviceAlarms(appId: string): any;
|
|
13
|
+
subscribeUserOneDeviceAlarms(appId: string): any;
|
|
13
14
|
registerSystemVariableHandler?(variableName: string, getValue: () => Promise<any>, setValue: (value: any) => Promise<void>): void;
|
|
14
15
|
notifySystemVariableChange?(variableName: string, value: any): void;
|
|
15
16
|
dispose(): any;
|
|
@@ -16,5 +16,6 @@ export declare class PerViewVariableCommunicator implements VariableCommunicator
|
|
|
16
16
|
subscribeVariableState(variableName: string): Observable<VariableState>;
|
|
17
17
|
subscribeVariableStates(variableNames: string[]): Observable<Array<VariableState>>;
|
|
18
18
|
subscribeUserDeviceAlarms(appId?: string): Observable<any[]>;
|
|
19
|
+
subscribeUserOneDeviceAlarms(appId?: string): Observable<any>;
|
|
19
20
|
dispose(): void;
|
|
20
21
|
}
|
|
@@ -51,6 +51,12 @@ export class PerViewVariableCommunicator {
|
|
|
51
51
|
this.alarmSubscription.push(subscription);
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
|
+
subscribeUserOneDeviceAlarms(appId = '') {
|
|
55
|
+
return new Observable(subscriber => {
|
|
56
|
+
const subscription = this._rawVariableCommunicator.subscribeUserOneDeviceAlarms(appId).subscribe((value) => subscriber.next(value), (error) => subscriber.error(error), () => subscriber.complete());
|
|
57
|
+
this.alarmSubscription.push(subscription);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
54
60
|
dispose() {
|
|
55
61
|
forEach(this.variableValuesChangedSubscriptions, s => s.unsubscribe());
|
|
56
62
|
forEach(this.variableStatesChangedSubscription, s => s.unsubscribe());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"PerViewVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../communication","name":"VariableCommunicator","line":15,"character":38}]}],"openVariable":[{"__symbolic":"method"}],"openVariables":[{"__symbolic":"method"}],"write":[{"__symbolic":"method"}],"writeWordByBit":[{"__symbolic":"method"}],"requestVirtualDeviceState":[{"__symbolic":"method"}],"subscribeVariableState":[{"__symbolic":"method"}],"subscribeVariableStates":[{"__symbolic":"method"}],"subscribeUserDeviceAlarms":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"PerViewVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../communication","name":"VariableCommunicator","line":15,"character":38}]}],"openVariable":[{"__symbolic":"method"}],"openVariables":[{"__symbolic":"method"}],"write":[{"__symbolic":"method"}],"writeWordByBit":[{"__symbolic":"method"}],"requestVirtualDeviceState":[{"__symbolic":"method"}],"subscribeVariableState":[{"__symbolic":"method"}],"subscribeVariableStates":[{"__symbolic":"method"}],"subscribeUserDeviceAlarms":[{"__symbolic":"method"}],"subscribeUserOneDeviceAlarms":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
|
|
@@ -17,7 +17,9 @@ export declare class ScrollAlarmElement extends ConditionalDynamicDisplayElement
|
|
|
17
17
|
private endTime;
|
|
18
18
|
private getAlarmDataId;
|
|
19
19
|
private alarmRefreshThrottleId;
|
|
20
|
-
private
|
|
20
|
+
private alarmRefreshSubscription;
|
|
21
|
+
private signalRSubscription;
|
|
22
|
+
private isReplacingContent;
|
|
21
23
|
private isScrolling;
|
|
22
24
|
private isDisposed;
|
|
23
25
|
private isRefreshingCurrentPage;
|
|
@@ -36,12 +38,14 @@ export declare class ScrollAlarmElement extends ConditionalDynamicDisplayElement
|
|
|
36
38
|
private headerFont;
|
|
37
39
|
private hasTriedFirstPage;
|
|
38
40
|
private isSimulateMode;
|
|
41
|
+
private _canvasCtx;
|
|
39
42
|
constructor(element: HTMLElement, injector: Injector, permissionChecker: PermissionChecker, variableCommunicator: VariableCommunicator, variableStore: VariableStore, alarmsStore: AlarmsStore, signalRAppId: string);
|
|
40
43
|
dispose(): void;
|
|
41
44
|
private getAlarmData;
|
|
42
45
|
private initDisplayContainer;
|
|
43
46
|
private _buildFontAttrs;
|
|
44
47
|
private _createSvgTextNode;
|
|
48
|
+
private _measureTextWithCanvas;
|
|
45
49
|
private _getSvgTextWidth;
|
|
46
50
|
private _updateUnderlineWidth;
|
|
47
51
|
private renderNewPage;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as d3 from 'd3';
|
|
2
1
|
import { ConditionalDynamicDisplayElement } from '../base/conditional-dynamic-display-element';
|
|
3
2
|
import { GetAlarmsArgs } from '../../config';
|
|
4
3
|
import * as moment from 'moment';
|
|
@@ -15,7 +14,7 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
15
14
|
this.alarmsStore = alarmsStore;
|
|
16
15
|
this.elementStatus = ScrollAlarmElementStatus.Loading;
|
|
17
16
|
this.alarmNames = [];
|
|
18
|
-
this.
|
|
17
|
+
this.isReplacingContent = false; // 标记是否正在替换内容(防止并发执行)
|
|
19
18
|
this.isScrolling = false;
|
|
20
19
|
this.isDisposed = false;
|
|
21
20
|
this.isRefreshingCurrentPage = false; // 标记是否正在刷新当前页(而不是加载新页)
|
|
@@ -31,6 +30,7 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
31
30
|
this.isLoadingNextPage = false;
|
|
32
31
|
this.hasTriedFirstPage = false; // 是否已经尝试加载过第一页
|
|
33
32
|
this.isSimulateMode = false; // 是否是模拟运行模式
|
|
33
|
+
this._canvasCtx = null;
|
|
34
34
|
this.rootElement.selectAll('*').remove();
|
|
35
35
|
this.setStatusAsLoading();
|
|
36
36
|
this.logger = injector.get(LOGGER_SERVICE_TOKEN);
|
|
@@ -54,26 +54,16 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
54
54
|
else {
|
|
55
55
|
// 真实运行模式:使用原有的数据查询逻辑
|
|
56
56
|
this.updateQueryTimeRange();
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// 设置节流定时器,1秒后执行
|
|
68
|
-
this.alarmRefreshThrottleId = setTimeout(() => {
|
|
69
|
-
// 收到新告警消息,实时替换当前滚动内容,不影响滚动
|
|
70
|
-
this.replaceCurrentScrollingContent();
|
|
71
|
-
// 重置等待刷新标志
|
|
72
|
-
this.isWaitingForAlarmRefresh = false;
|
|
73
|
-
}, 1000);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
});
|
|
57
|
+
// 监听单设备告警更新(防抖:连续推送只取最后一次)
|
|
58
|
+
// 保存订阅对象,dispose 时取消,防止组件销毁后仍触发回调
|
|
59
|
+
this.signalRSubscription = variableCommunicator.subscribeUserOneDeviceAlarms(signalRAppId).subscribe((alarmWithAppId) => {
|
|
60
|
+
const alarm = alarmWithAppId.alarm;
|
|
61
|
+
if (this.alarmNames.indexOf(alarm.name) !== -1) {
|
|
62
|
+
clearTimeout(this.alarmRefreshThrottleId);
|
|
63
|
+
this.alarmRefreshThrottleId = setTimeout(() => {
|
|
64
|
+
this.replaceCurrentScrollingContent();
|
|
65
|
+
}, 300);
|
|
66
|
+
}
|
|
77
67
|
});
|
|
78
68
|
// 初始化显示容器
|
|
79
69
|
this.initDisplayContainer();
|
|
@@ -102,10 +92,19 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
102
92
|
clearInterval(this.scrollIntervalId);
|
|
103
93
|
clearTimeout(this.getAlarmDataId);
|
|
104
94
|
clearTimeout(this.alarmRefreshThrottleId);
|
|
95
|
+
// 取消 HTTP 请求订阅,防止 dispose 后回调仍然操作已卸载的 DOM
|
|
96
|
+
if (this.alarmRefreshSubscription) {
|
|
97
|
+
this.alarmRefreshSubscription.unsubscribe();
|
|
98
|
+
this.alarmRefreshSubscription = null;
|
|
99
|
+
}
|
|
100
|
+
// 取消 SignalR 推送订阅,防止 dispose 后继续触发 replaceCurrentScrollingContent
|
|
101
|
+
if (this.signalRSubscription) {
|
|
102
|
+
this.signalRSubscription.unsubscribe();
|
|
103
|
+
this.signalRSubscription = null;
|
|
104
|
+
}
|
|
105
105
|
if (this.element && this.element.tooltip) {
|
|
106
106
|
this.element.tooltip.hidden(true);
|
|
107
107
|
}
|
|
108
|
-
this.logger.debug(`[GUI]Dispose Scroll Alarm Refresh Interval:${d3.time.format('%x %X')(new Date())}`);
|
|
109
108
|
// 重置所有状态
|
|
110
109
|
this.isScrolling = false;
|
|
111
110
|
}
|
|
@@ -323,14 +322,35 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
323
322
|
}
|
|
324
323
|
return g;
|
|
325
324
|
}
|
|
325
|
+
_measureTextWithCanvas(textContent, fontSize, fontFamily, isBold, isItalic) {
|
|
326
|
+
if (!this._canvasCtx) {
|
|
327
|
+
const canvas = document.createElement('canvas');
|
|
328
|
+
this._canvasCtx = canvas.getContext('2d');
|
|
329
|
+
}
|
|
330
|
+
if (!this._canvasCtx) {
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
const weight = isBold ? 'bold' : 'normal';
|
|
334
|
+
const style = isItalic ? 'italic' : 'normal';
|
|
335
|
+
this._canvasCtx.font = `${style} ${weight} ${fontSize}px ${fontFamily}`;
|
|
336
|
+
return this._canvasCtx.measureText(textContent).width;
|
|
337
|
+
}
|
|
326
338
|
_getSvgTextWidth(g) {
|
|
339
|
+
var _a, _b, _c, _d;
|
|
327
340
|
const text = g.querySelector('text');
|
|
328
341
|
if (!text) {
|
|
329
342
|
return 100;
|
|
330
343
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
344
|
+
const len = (_b = (_a = text).getComputedTextLength) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
345
|
+
if (len > 0)
|
|
346
|
+
return len;
|
|
347
|
+
const bbox = (_d = (_c = text).getBBox) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
348
|
+
if ((bbox === null || bbox === void 0 ? void 0 : bbox.width) > 0)
|
|
349
|
+
return bbox.width;
|
|
350
|
+
// SVG 节点游离于 DOM 外时 getComputedTextLength/getBBox 均返回 0,
|
|
351
|
+
// 改用 Canvas measureText 离屏计算
|
|
352
|
+
const fa = this._buildFontAttrs();
|
|
353
|
+
return this._measureTextWithCanvas(text.textContent || '', fa.fontSize, fa.fontFamily, fa.isBold, fa.isItalic);
|
|
334
354
|
}
|
|
335
355
|
_updateUnderlineWidth(g, width) {
|
|
336
356
|
const underline = g.querySelector('line.text-underline');
|
|
@@ -378,7 +398,7 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
378
398
|
this.pageWidths.push(pageWidth);
|
|
379
399
|
this.totalWidth += (this.totalWidth > 0 && pageWidth > 0 ? GAP : 0) + pageWidth;
|
|
380
400
|
}
|
|
381
|
-
_rebaseTextNodes() {
|
|
401
|
+
_rebaseTextNodes(onDone) {
|
|
382
402
|
const GAP = 80;
|
|
383
403
|
let x = 0;
|
|
384
404
|
Array.from(this.allAlarmsContainer.children).forEach(node => {
|
|
@@ -390,6 +410,8 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
390
410
|
const newTotal = x > 0 ? x - GAP : 0;
|
|
391
411
|
this.totalWidth = newTotal;
|
|
392
412
|
this.pageWidths = [newTotal];
|
|
413
|
+
if (onDone)
|
|
414
|
+
onDone();
|
|
393
415
|
}
|
|
394
416
|
removeOldestPage() {
|
|
395
417
|
// 移除最旧的一页数据
|
|
@@ -447,8 +469,9 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
447
469
|
}
|
|
448
470
|
else {
|
|
449
471
|
// 单页循环:重排 x 从 0 开始,currentLeft 重置到右侧
|
|
450
|
-
this._rebaseTextNodes()
|
|
451
|
-
|
|
472
|
+
this._rebaseTextNodes(() => {
|
|
473
|
+
this.currentLeft = this.model.size.width;
|
|
474
|
+
});
|
|
452
475
|
}
|
|
453
476
|
}
|
|
454
477
|
}
|
|
@@ -678,6 +701,17 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
678
701
|
*/
|
|
679
702
|
replaceCurrentScrollingContent() {
|
|
680
703
|
var _a, _b;
|
|
704
|
+
// 防止并发执行:如果正在替换内容,直接返回
|
|
705
|
+
if (this.isReplacingContent) {
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
this.isReplacingContent = true;
|
|
709
|
+
// 暂停滚动定时器,防止在内容更新过程中 scrollContent 读取到中间状态导致重叠
|
|
710
|
+
clearInterval(this.scrollIntervalId);
|
|
711
|
+
if (this.alarmRefreshSubscription) {
|
|
712
|
+
this.alarmRefreshSubscription.unsubscribe();
|
|
713
|
+
this.alarmRefreshSubscription = null;
|
|
714
|
+
}
|
|
681
715
|
// 更新查询时间范围
|
|
682
716
|
this.updateQueryTimeRange();
|
|
683
717
|
// 查询所有当前应该显示的数据(查询足够多的数据以确保包含所有新增/删除)
|
|
@@ -699,7 +733,7 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
699
733
|
: undefined;
|
|
700
734
|
const input = new GetAlarmsArgs(this.alarmNames, this.startTime, this.endTime, queryCount, 0, // skipCount
|
|
701
735
|
stateFilter, sorting);
|
|
702
|
-
this.alarmsStore.getHistoryAlarms(input).subscribe(result => {
|
|
736
|
+
this.alarmRefreshSubscription = this.alarmsStore.getHistoryAlarms(input).subscribe(result => {
|
|
703
737
|
if (!result.error && result.items) {
|
|
704
738
|
const newItems = result.items;
|
|
705
739
|
// 如果没有数据,清空显示
|
|
@@ -718,6 +752,9 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
718
752
|
this.currentLeft = this.model.size.width;
|
|
719
753
|
this.allAlarmsContainer.setAttribute('transform', `translate(${this.currentLeft}, 0)`);
|
|
720
754
|
}
|
|
755
|
+
this.isReplacingContent = false;
|
|
756
|
+
// 无数据时停止滚动(scrollContent 会因 displayedItems.length === 0 直接返回)
|
|
757
|
+
this.isScrolling = false;
|
|
721
758
|
return;
|
|
722
759
|
}
|
|
723
760
|
// 如果是首次加载或当前没有数据,直接渲染并启动滚动
|
|
@@ -734,10 +771,13 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
734
771
|
this.currentLeft = this.model.size.width;
|
|
735
772
|
this.allAlarmsContainer.setAttribute('transform', `translate(${this.currentLeft}, 0)`);
|
|
736
773
|
this.renderNewPage(newItems);
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
774
|
+
requestAnimationFrame(() => {
|
|
775
|
+
this._rebaseTextNodes(() => {
|
|
776
|
+
this.isReplacingContent = false;
|
|
777
|
+
this.isScrolling = false;
|
|
778
|
+
this.initScrolling();
|
|
779
|
+
});
|
|
780
|
+
});
|
|
741
781
|
return;
|
|
742
782
|
}
|
|
743
783
|
// 保存当前的滚动位置
|
|
@@ -752,10 +792,30 @@ export class ScrollAlarmElement extends ConditionalDynamicDisplayElement {
|
|
|
752
792
|
// 更新状态
|
|
753
793
|
this.displayedItems = newItems;
|
|
754
794
|
this.hasMoreData = result.totalCount > newItems.length;
|
|
755
|
-
//
|
|
756
|
-
|
|
757
|
-
|
|
795
|
+
// renderNewPage 里 getComputedTextLength 在刚 append 时可能返回 0,
|
|
796
|
+
// 延迟一帧让浏览器完成布局后用 _rebaseTextNodes 修正所有节点位置
|
|
797
|
+
requestAnimationFrame(() => {
|
|
798
|
+
this._rebaseTextNodes(() => {
|
|
799
|
+
// 保持滚动位置不变,内容更新完成后重新启动滚动
|
|
800
|
+
this.currentLeft = currentScrollPosition;
|
|
801
|
+
this.allAlarmsContainer.setAttribute('transform', `translate(${this.currentLeft}, 0)`);
|
|
802
|
+
this.isReplacingContent = false;
|
|
803
|
+
this.isScrolling = false;
|
|
804
|
+
this.initScrolling();
|
|
805
|
+
});
|
|
806
|
+
});
|
|
807
|
+
return;
|
|
758
808
|
}
|
|
809
|
+
// 重置标志,内容更新完成后重新启动滚动
|
|
810
|
+
this.isReplacingContent = false;
|
|
811
|
+
this.isScrolling = false;
|
|
812
|
+
this.initScrolling();
|
|
813
|
+
}, (error) => {
|
|
814
|
+
// 错误处理:重置标志,恢复滚动
|
|
815
|
+
this.isReplacingContent = false;
|
|
816
|
+
this.isScrolling = false;
|
|
817
|
+
this.initScrolling();
|
|
818
|
+
this.logger.error('Failed to replace scrolling content:', error);
|
|
759
819
|
});
|
|
760
820
|
}
|
|
761
821
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"ScrollAlarmElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-dynamic-display-element","name":"ConditionalDynamicDisplayElement","line":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"ScrollAlarmElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-dynamic-display-element","name":"ConditionalDynamicDisplayElement","line":16,"character":40},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":54,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":55,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":56,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":57,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":58,"character":23},{"__symbolic":"reference","module":"../../config","name":"AlarmsStore","line":59,"character":38},{"__symbolic":"reference","name":"string"}]}],"dispose":[{"__symbolic":"method"}],"getAlarmData":[{"__symbolic":"method"}],"initDisplayContainer":[{"__symbolic":"method"}],"_buildFontAttrs":[{"__symbolic":"method"}],"_createSvgTextNode":[{"__symbolic":"method"}],"_measureTextWithCanvas":[{"__symbolic":"method"}],"_getSvgTextWidth":[{"__symbolic":"method"}],"_updateUnderlineWidth":[{"__symbolic":"method"}],"renderNewPage":[{"__symbolic":"method"}],"_rebaseTextNodes":[{"__symbolic":"method"}],"removeOldestPage":[{"__symbolic":"method"}],"scrollContent":[{"__symbolic":"method"}],"initScrolling":[{"__symbolic":"method"}],"resetToFirstPage":[{"__symbolic":"method"}],"updateQueryTimeRange":[{"__symbolic":"method"}],"setStatusAsNormal":[{"__symbolic":"method"}],"setStatusAsLoading":[{"__symbolic":"method"}],"renderStatus":[{"__symbolic":"method"}],"clearStatus":[{"__symbolic":"method"}],"renderStaticDisplay":[{"__symbolic":"method"}],"initStaticScrolling":[{"__symbolic":"method"}],"scrollStaticContent":[{"__symbolic":"method"}],"replaceCurrentScrollingContent":[{"__symbolic":"method"}]}}}}]
|
package/package.json
CHANGED
|
@@ -41,6 +41,7 @@ export declare class RemoteVariableCommunicator implements VariableCommunicator
|
|
|
41
41
|
write(variableName: string, value: any): Observable<VariableValue>;
|
|
42
42
|
writeWordByBit(variableName: string, index: number, value: number): Observable<VariableValue>;
|
|
43
43
|
subscribeUserDeviceAlarms(appId?: string): Observable<any[]>;
|
|
44
|
+
subscribeUserOneDeviceAlarms(appId?: string): Observable<any>;
|
|
44
45
|
/**
|
|
45
46
|
* 注册系统变量处理器
|
|
46
47
|
* @param variableName 变量名(如"当前语种ID")
|
|
@@ -351,6 +351,16 @@ export class RemoteVariableCommunicator {
|
|
|
351
351
|
};
|
|
352
352
|
});
|
|
353
353
|
}
|
|
354
|
+
subscribeUserOneDeviceAlarms(appId = '') {
|
|
355
|
+
return new Observable(observer => {
|
|
356
|
+
const subscription = this.remoteVariableProtocol.historyAlarmChanged.subscribe(value => observer.next(value), error => observer.error(error), () => observer.complete());
|
|
357
|
+
this.remoteVariableProtocol.subscribeUserOneDeviceAlarms(appId);
|
|
358
|
+
return () => {
|
|
359
|
+
subscription.unsubscribe();
|
|
360
|
+
this.remoteVariableProtocol.unsubscribeUserOneDeviceAlarms(appId);
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
}
|
|
354
364
|
/**
|
|
355
365
|
* 注册系统变量处理器
|
|
356
366
|
* @param variableName 变量名(如"当前语种ID")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"RemoteVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"./remote-variable-protocol","name":"RemoteVariableProtocol","line":38,"character":57},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":38,"character":106}]}],"doAlarmChanged":[{"__symbolic":"method"}],"doVariableValuesChanged":[{"__symbolic":"method"}],"doVirtualDeviceStatesChanged":[{"__symbolic":"method"}],"doVariableStatesChanged":[{"__symbolic":"method"}],"setOfflineValueCache":[{"__symbolic":"method"}],"subscribeVariableStates":[{"__symbolic":"method"}],"subscribeVariableState":[{"__symbolic":"method"}],"requestVirtualDeviceState":[{"__symbolic":"method"}],"openVariables":[{"__symbolic":"method"}],"openVariable":[{"__symbolic":"method"}],"write":[{"__symbolic":"method"}],"writeWordByBit":[{"__symbolic":"method"}],"subscribeUserDeviceAlarms":[{"__symbolic":"method"}],"registerSystemVariableHandler":[{"__symbolic":"method"}],"notifySystemVariableChange":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"RemoteVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"./remote-variable-protocol","name":"RemoteVariableProtocol","line":38,"character":57},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":38,"character":106}]}],"doAlarmChanged":[{"__symbolic":"method"}],"doVariableValuesChanged":[{"__symbolic":"method"}],"doVirtualDeviceStatesChanged":[{"__symbolic":"method"}],"doVariableStatesChanged":[{"__symbolic":"method"}],"setOfflineValueCache":[{"__symbolic":"method"}],"subscribeVariableStates":[{"__symbolic":"method"}],"subscribeVariableState":[{"__symbolic":"method"}],"requestVirtualDeviceState":[{"__symbolic":"method"}],"openVariables":[{"__symbolic":"method"}],"openVariable":[{"__symbolic":"method"}],"write":[{"__symbolic":"method"}],"writeWordByBit":[{"__symbolic":"method"}],"subscribeUserDeviceAlarms":[{"__symbolic":"method"}],"subscribeUserOneDeviceAlarms":[{"__symbolic":"method"}],"registerSystemVariableHandler":[{"__symbolic":"method"}],"notifySystemVariableChange":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
|
|
@@ -15,4 +15,7 @@ export interface RemoteVariableProtocol {
|
|
|
15
15
|
unsubscribeVariableStates(variableNames: string[]): Observable<void>;
|
|
16
16
|
subscribeVirtualDeviceAlarms(appId: string): any;
|
|
17
17
|
unsubscribeVirtualDeviceAlarms(appId: string): any;
|
|
18
|
+
subscribeUserOneDeviceAlarms(appId: string): any;
|
|
19
|
+
unsubscribeUserOneDeviceAlarms(appId: string): any;
|
|
20
|
+
historyAlarmChanged: Observable<any>;
|
|
18
21
|
}
|