@flexem/fc-gui 3.0.0-alpha.150 → 3.0.0-alpha.151
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 +67 -17
- package/bundles/@flexem/fc-gui.umd.js.map +1 -1
- package/bundles/@flexem/fc-gui.umd.min.js +1 -1
- package/bundles/@flexem/fc-gui.umd.min.js.map +1 -1
- package/elements/base/readable-element.js +1 -1
- package/elements/per-view-variable-communicator.d.ts +1 -1
- package/elements/per-view-variable-communicator.js +5 -2
- package/elements/switch-indicator-light/bit-indicator-light-operator.d.ts +1 -0
- package/elements/switch-indicator-light/bit-indicator-light-operator.js +5 -2
- package/elements/switch-indicator-light/bit-indicator-light-operator.metadata.json +1 -1
- package/elements/switch-indicator-light/switch-indicator-light-element.js +9 -4
- package/elements/switch-indicator-light/word-indicator-light-operator.d.ts +1 -0
- package/elements/switch-indicator-light/word-indicator-light-operator.js +5 -2
- package/elements/switch-indicator-light/word-indicator-light-operator.metadata.json +1 -1
- package/gui/gui-view.d.ts +2 -1
- package/gui/gui-view.js +13 -5
- package/gui/gui-view.metadata.json +1 -1
- package/package.json +1 -1
- package/remote/communication/variable/remote-variable-communicator.d.ts +5 -0
- package/remote/communication/variable/remote-variable-communicator.js +26 -1
- package/remote/communication/variable/remote-variable-communicator.metadata.json +1 -1
|
@@ -112,7 +112,7 @@ export class ReadableElement extends ConditionalEnableElement {
|
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
// 处理普通变量
|
|
115
|
-
if (this.state === State.Normal || this.state === State.Disable
|
|
115
|
+
if (this.state === State.Normal || this.state === State.Disable || this.state === State.Offline
|
|
116
116
|
|| value.variableName === this.minVariableName
|
|
117
117
|
|| value.variableName === this.maxVariableName) {
|
|
118
118
|
this.updateVariableValue(value.value, value.variableName);
|
|
@@ -15,6 +15,6 @@ export declare class PerViewVariableCommunicator implements VariableCommunicator
|
|
|
15
15
|
requestVirtualDeviceState(): Observable<void>;
|
|
16
16
|
subscribeVariableState(variableName: string): Observable<VariableState>;
|
|
17
17
|
subscribeVariableStates(variableNames: string[]): Observable<Array<VariableState>>;
|
|
18
|
-
subscribeUserDeviceAlarms(appId?: string): Observable<
|
|
18
|
+
subscribeUserDeviceAlarms(appId?: string): Observable<any[]>;
|
|
19
19
|
dispose(): void;
|
|
20
20
|
}
|
|
@@ -18,7 +18,10 @@ export class PerViewVariableCommunicator {
|
|
|
18
18
|
if (!this.observers.has(variableName)) {
|
|
19
19
|
this.observers.set(variableName, []);
|
|
20
20
|
}
|
|
21
|
-
this.observers.get(variableName)
|
|
21
|
+
const obs = this.observers.get(variableName);
|
|
22
|
+
if (obs) {
|
|
23
|
+
obs.push(subscriber);
|
|
24
|
+
}
|
|
22
25
|
});
|
|
23
26
|
const subscription = this._rawVariableCommunicator.openVariables(variableNames, appId).subscribe(values => subscriber.next(values), error => subscriber.error(error), () => subscriber.complete());
|
|
24
27
|
this.variableValuesChangedSubscriptions.push(subscription);
|
|
@@ -44,7 +47,7 @@ export class PerViewVariableCommunicator {
|
|
|
44
47
|
}
|
|
45
48
|
subscribeUserDeviceAlarms(appId = '') {
|
|
46
49
|
return new Observable(subscriber => {
|
|
47
|
-
const subscription = this._rawVariableCommunicator.subscribeUserDeviceAlarms(appId).subscribe(values => subscriber.next(values), error => subscriber.error(error), () => subscriber.complete());
|
|
50
|
+
const subscription = this._rawVariableCommunicator.subscribeUserDeviceAlarms(appId).subscribe((values) => subscriber.next(values), (error) => subscriber.error(error), () => subscriber.complete());
|
|
48
51
|
this.alarmSubscription.push(subscription);
|
|
49
52
|
});
|
|
50
53
|
}
|
|
@@ -11,6 +11,7 @@ export declare class BitIndicatorLightOperator implements IndicatorLightOperator
|
|
|
11
11
|
private binary;
|
|
12
12
|
currentStateId?: number;
|
|
13
13
|
currentStateIdChanged: EventEmitter<CurrentStateIdValue>;
|
|
14
|
+
private valueSubscription;
|
|
14
15
|
private offStateId?;
|
|
15
16
|
private onStateId?;
|
|
16
17
|
get variableName(): string;
|
|
@@ -55,8 +55,11 @@ export class BitIndicatorLightOperator {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
requestCurrentSateIdValue(variableCommunicator, appId = '') {
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
if (this.valueSubscription) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.valueSubscription = variableCommunicator.openVariable(this.variableName, appId).subscribe(value => {
|
|
62
|
+
if (value.state === VariableStateEnum.DataNormal || value.state === VariableStateEnum.Offline) {
|
|
60
63
|
if (this.settings.isBitwiseIndex) {
|
|
61
64
|
const maxBitIndex = 31;
|
|
62
65
|
this.binary = new Binary(value.value, maxBitIndex + 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"BitIndicatorLightOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"BitIndicatorLightSettings","line":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"BitIndicatorLightOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"BitIndicatorLightSettings","line":27,"character":43},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"../../model","name":"SwitchIndicatorState","line":28,"character":16}]},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":29,"character":47},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":30,"character":40}]}],"requestData":[{"__symbolic":"method"}],"requestCurrentSateIdValue":[{"__symbolic":"method"}]}}}}]
|
|
@@ -217,12 +217,17 @@ export class SwitchIndicatorLightElement extends ConditionalEnableElement {
|
|
|
217
217
|
this.indicatorLightOperator.requestData(this.signalRAppId);
|
|
218
218
|
}
|
|
219
219
|
currentStateIdChange(statusIdValue) {
|
|
220
|
-
if (!isUndefined(statusIdValue.value)) {
|
|
221
|
-
this.switchToState(statusIdValue.value);
|
|
222
|
-
}
|
|
223
220
|
this.updateElementStates([statusIdValue.state]);
|
|
224
221
|
if (this.state === State.Unbind || this.state === State.Offline) {
|
|
225
|
-
|
|
222
|
+
if (!isUndefined(statusIdValue.value)) {
|
|
223
|
+
this.switchToState(statusIdValue.value);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
this.switchToState(0);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
else if (!isUndefined(statusIdValue.value)) {
|
|
230
|
+
this.switchToState(statusIdValue.value);
|
|
226
231
|
}
|
|
227
232
|
}
|
|
228
233
|
switchToState(stateId) {
|
|
@@ -10,6 +10,7 @@ export declare class WordIndicatorLightOperator implements IndicatorLightOperato
|
|
|
10
10
|
private readonly variableStore;
|
|
11
11
|
currentStateId?: number;
|
|
12
12
|
currentStateIdChanged: EventEmitter<CurrentStateIdValue>;
|
|
13
|
+
private valueSubscription;
|
|
13
14
|
private sortedStates;
|
|
14
15
|
get variableName(): string;
|
|
15
16
|
constructor(settings: WordIndicatorLightSettings, states: SwitchIndicatorState[], variableCommunicator: VariableCommunicator, variableStore: VariableStore);
|
|
@@ -36,9 +36,12 @@ export class WordIndicatorLightOperator {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
requestCurrentSateIdValue(variableCommunicator, appId = '') {
|
|
39
|
+
if (this.valueSubscription) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
39
42
|
// TODO 检查状态id是从0-n连续编号的。
|
|
40
|
-
variableCommunicator.openVariable(this.variableName, appId).subscribe(value => {
|
|
41
|
-
if (value.state === VariableStateEnum.DataNormal) {
|
|
43
|
+
this.valueSubscription = variableCommunicator.openVariable(this.variableName, appId).subscribe(value => {
|
|
44
|
+
if (value.state === VariableStateEnum.DataNormal || value.state === VariableStateEnum.Offline) {
|
|
42
45
|
let stateId = 0;
|
|
43
46
|
for (let index = 0; index < this.sortedStates.length - 1; index++) {
|
|
44
47
|
const element = this.sortedStates[index];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"WordIndicatorLightOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"WordIndicatorLightSettings","line":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"WordIndicatorLightOperator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../model","name":"WordIndicatorLightSettings","line":24,"character":43},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"../../model","name":"SwitchIndicatorState","line":25,"character":16}]},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":26,"character":47},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":27,"character":40}]}],"requestData":[{"__symbolic":"method"}],"requestCurrentSateIdValue":[{"__symbolic":"method"}]}}}}]
|
package/gui/gui-view.d.ts
CHANGED
|
@@ -23,7 +23,8 @@ export declare class GuiView implements PopupViewService {
|
|
|
23
23
|
private openVariableStatesSubscription;
|
|
24
24
|
private requestVirtualDeviceState;
|
|
25
25
|
private virtualDeviceStatesChanged;
|
|
26
|
-
private
|
|
26
|
+
private openVariablesSubscriptions;
|
|
27
|
+
private openedVariableNamesForValues;
|
|
27
28
|
private openedVariableNames;
|
|
28
29
|
private perViewVariableCommunicator;
|
|
29
30
|
private svgRootClass;
|
package/gui/gui-view.js
CHANGED
|
@@ -16,6 +16,8 @@ export class GuiView {
|
|
|
16
16
|
this.context = context;
|
|
17
17
|
this.parentView = parentView;
|
|
18
18
|
this.viewId = Guid.newGuid().toString('n');
|
|
19
|
+
this.openVariablesSubscriptions = [];
|
|
20
|
+
this.openedVariableNamesForValues = new Set();
|
|
19
21
|
this.logger = injector.get(LOGGER_SERVICE_TOKEN);
|
|
20
22
|
this.childViews = new Array();
|
|
21
23
|
if (parentView) {
|
|
@@ -71,6 +73,9 @@ export class GuiView {
|
|
|
71
73
|
if (this.openVariableStatesSubscription) {
|
|
72
74
|
this.openVariableStatesSubscription.unsubscribe();
|
|
73
75
|
}
|
|
76
|
+
this.openVariablesSubscriptions.forEach(s => s.unsubscribe());
|
|
77
|
+
this.openVariablesSubscriptions = [];
|
|
78
|
+
this.openedVariableNamesForValues.clear();
|
|
74
79
|
this.openedVariableNames = this.mainElement.getVariableNames();
|
|
75
80
|
// 分离系统变量和普通变量
|
|
76
81
|
const systemVariables = [];
|
|
@@ -110,7 +115,7 @@ export class GuiView {
|
|
|
110
115
|
this.mainElement.reportVariableStates(states);
|
|
111
116
|
const normalVariableNames = [];
|
|
112
117
|
each(states, v => {
|
|
113
|
-
if (v.state === VariableStateEnum.Normal && normalVariableNames.indexOf(v.variableName) === -1) {
|
|
118
|
+
if ((v.state === VariableStateEnum.Normal || v.state === VariableStateEnum.Offline) && normalVariableNames.indexOf(v.variableName) === -1) {
|
|
114
119
|
normalVariableNames.push(v.variableName);
|
|
115
120
|
}
|
|
116
121
|
});
|
|
@@ -217,8 +222,8 @@ export class GuiView {
|
|
|
217
222
|
if (this.virtualDeviceStatesChanged) {
|
|
218
223
|
this.virtualDeviceStatesChanged.unsubscribe();
|
|
219
224
|
}
|
|
220
|
-
if (this.
|
|
221
|
-
this.
|
|
225
|
+
if (this.openVariablesSubscriptions) {
|
|
226
|
+
this.openVariablesSubscriptions.forEach(s => s.unsubscribe());
|
|
222
227
|
}
|
|
223
228
|
if (this.perViewVariableCommunicator) {
|
|
224
229
|
this.perViewVariableCommunicator.dispose();
|
|
@@ -232,9 +237,12 @@ export class GuiView {
|
|
|
232
237
|
this.logger.debug('[GUI] View disposed.');
|
|
233
238
|
}
|
|
234
239
|
normalOpenedVariableNames(normalVariableNames) {
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
const newVariables = normalVariableNames.filter(v => !this.openedVariableNamesForValues.has(v));
|
|
241
|
+
if (newVariables.length > 0) {
|
|
242
|
+
newVariables.forEach(v => this.openedVariableNamesForValues.add(v));
|
|
243
|
+
const sub = this.perViewVariableCommunicator.openVariables(newVariables, this.signalRAppId)
|
|
237
244
|
.subscribe(variableValues => this.mainElement.reportVariableValues(variableValues));
|
|
245
|
+
this.openVariablesSubscriptions.push(sub);
|
|
238
246
|
}
|
|
239
247
|
}
|
|
240
248
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"GuiView":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"GuiView":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":50,"character":43},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":51,"character":41},{"__symbolic":"reference","module":"./gui-context","name":"GuiContext","line":52,"character":34},{"__symbolic":"reference","name":"GuiView"}]}],"resize":[{"__symbolic":"method"}],"load":[{"__symbolic":"method"}],"loadElementState":[{"__symbolic":"method"}],"popView":[{"__symbolic":"method"}],"closeView":[{"__symbolic":"method"}],"moveView":[{"__symbolic":"method"}],"showMusk":[{"__symbolic":"method"}],"showShadow":[{"__symbolic":"method"}],"hideMusk":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}],"normalOpenedVariableNames":[{"__symbolic":"method"}]}}}}]
|
package/package.json
CHANGED
|
@@ -21,11 +21,16 @@ export declare class RemoteVariableCommunicator implements VariableCommunicator
|
|
|
21
21
|
private alarmObservers;
|
|
22
22
|
private alarmChangedSubscription;
|
|
23
23
|
private systemVariableHandlers;
|
|
24
|
+
private offlineValueCache;
|
|
24
25
|
constructor(remoteVariableProtocol: RemoteVariableProtocol, logger: LoggerService);
|
|
25
26
|
private doAlarmChanged;
|
|
26
27
|
private doVariableValuesChanged;
|
|
27
28
|
private doVirtualDeviceStatesChanged;
|
|
28
29
|
private doVariableStatesChanged;
|
|
30
|
+
/**
|
|
31
|
+
* 预填充离线变量值缓存,由 GuiContext 在组态加载时一次性调用
|
|
32
|
+
*/
|
|
33
|
+
setOfflineValueCache(variableName: string, value: any): void;
|
|
29
34
|
subscribeVariableStates(variableNames: string[]): Observable<VariableState[]>;
|
|
30
35
|
subscribeVariableState(variableName: string): Observable<VariableState>;
|
|
31
36
|
requestVirtualDeviceState(): Observable<void>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { each, remove, uniq } from 'lodash';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { map } from 'rxjs/operators';
|
|
4
|
+
import { VariableStateEnum } from '../../../communication';
|
|
4
5
|
import { StringifyingMap } from '../../../core';
|
|
5
6
|
export class RemoteVariableCommunicator {
|
|
6
7
|
constructor(remoteVariableProtocol, logger) {
|
|
@@ -13,6 +14,8 @@ export class RemoteVariableCommunicator {
|
|
|
13
14
|
this.alarmObservers = [];
|
|
14
15
|
// 系统变量处理器
|
|
15
16
|
this.systemVariableHandlers = new Map();
|
|
17
|
+
// 预加载的离线变量最新值缓存(组态加载时一次性填充,推送后即删除)
|
|
18
|
+
this.offlineValueCache = new Map();
|
|
16
19
|
this.variableValueCache = new StringifyingMap(k => JSON.stringify(k));
|
|
17
20
|
this.connectedSubscription = this.remoteVariableProtocol.connected.subscribe(() => {
|
|
18
21
|
const variableNamesToStart = [];
|
|
@@ -87,13 +90,35 @@ export class RemoteVariableCommunicator {
|
|
|
87
90
|
this.variableStateCache.set(variableName, state);
|
|
88
91
|
if (this.variableStateObservers.has(variableName)) {
|
|
89
92
|
each(this.variableStateObservers.get(variableName), ob => {
|
|
90
|
-
// TODO 同一个ob监听多个变量的情况,组合成数组一次推送。
|
|
91
93
|
ob.next([state]);
|
|
92
94
|
});
|
|
93
95
|
}
|
|
96
|
+
// 离线时从预加载缓存取值推送给值订阅者
|
|
97
|
+
if (state.state === VariableStateEnum.Offline && this.offlineValueCache.has(variableName)) {
|
|
98
|
+
const cachedValue = this.offlineValueCache.get(variableName);
|
|
99
|
+
const variableValue = {
|
|
100
|
+
variableName,
|
|
101
|
+
value: cachedValue,
|
|
102
|
+
state: VariableStateEnum.Offline
|
|
103
|
+
};
|
|
104
|
+
this.variableValueCache.set(variableName, variableValue);
|
|
105
|
+
if (this.observers.has(variableName)) {
|
|
106
|
+
each(this.observers.get(variableName), ob => {
|
|
107
|
+
ob.next([variableValue]);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// 无论什么状态,推送后清除缓存,防止后续再次离线时用旧值
|
|
112
|
+
this.offlineValueCache.delete(variableName);
|
|
94
113
|
});
|
|
95
114
|
});
|
|
96
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* 预填充离线变量值缓存,由 GuiContext 在组态加载时一次性调用
|
|
118
|
+
*/
|
|
119
|
+
setOfflineValueCache(variableName, value) {
|
|
120
|
+
this.offlineValueCache.set(variableName, value);
|
|
121
|
+
}
|
|
97
122
|
subscribeVariableStates(variableNames) {
|
|
98
123
|
return new Observable(observer => {
|
|
99
124
|
let variableNamesToStart = [];
|
|
@@ -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":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"RemoteVariableCommunicator":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"./remote-variable-protocol","name":"RemoteVariableProtocol","line":37,"character":57},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":37,"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"}]}}}}]
|