@flexem/fc-gui 3.0.0-alpha.150 → 3.0.0-alpha.152

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.
@@ -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);
@@ -67,7 +67,7 @@ export class CharacterDisplayElement extends ReadableElement {
67
67
  }
68
68
  changeStates() {
69
69
  super.changeStates();
70
- if (this.state === State.Normal || this.state === State.Disable) {
70
+ if (this.state === State.Normal || this.state === State.Disable || this.state === State.Offline) {
71
71
  this.updateDisplayValue(this.displayValue);
72
72
  }
73
73
  else {
@@ -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<VariableState[]>;
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).push(subscriber);
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
- variableCommunicator.openVariable(this.variableName, appId).subscribe(value => {
59
- if (value.state === VariableStateEnum.DataNormal) {
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":26,"character":43},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"../../model","name":"SwitchIndicatorState","line":27,"character":16}]},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":28,"character":47},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":29,"character":40}]}],"requestData":[{"__symbolic":"method"}],"requestCurrentSateIdValue":[{"__symbolic":"method"}]}}}}]
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
- this.switchToState(0);
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":23,"character":43},{"__symbolic":"reference","name":"Array","arguments":[{"__symbolic":"reference","module":"../../model","name":"SwitchIndicatorState","line":24,"character":16}]},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":25,"character":47},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":26,"character":40}]}],"requestData":[{"__symbolic":"method"}],"requestCurrentSateIdValue":[{"__symbolic":"method"}]}}}}]
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 openVariablesSubscription;
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.openVariablesSubscription) {
221
- this.openVariablesSubscription.unsubscribe();
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
- if (normalVariableNames.length > 0) {
236
- this.openVariablesSubscription = this.perViewVariableCommunicator.openVariables(normalVariableNames, this.signalRAppId)
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":49,"character":43},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":50,"character":41},{"__symbolic":"reference","module":"./gui-context","name":"GuiContext","line":51,"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"}]}}}}]
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main": "bundles/fc-gui.umd.js",
3
- "version": "3.0.0-alpha.150",
3
+ "version": "3.0.0-alpha.152",
4
4
  "module": "public_api.js",
5
5
  "typings": "public_api.d.ts",
6
6
  "license": "UNLICENSED",
@@ -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":34,"character":57},{"__symbolic":"reference","module":"../../../logger","name":"LoggerService","line":34,"character":106}]}],"doAlarmChanged":[{"__symbolic":"method"}],"doVariableValuesChanged":[{"__symbolic":"method"}],"doVirtualDeviceStatesChanged":[{"__symbolic":"method"}],"doVariableStatesChanged":[{"__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":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"}]}}}}]