@machinemetrics/io-adapter-lib 2.32.0
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/.circleci/config.yml +141 -0
- package/.eslintrc.json +36 -0
- package/.gitattributes +12 -0
- package/CHANGELOG.md +544 -0
- package/README.md +2 -0
- package/index.js +17 -0
- package/lib/config/adapterConfig.js +535 -0
- package/lib/config/common/allowDenyList.js +58 -0
- package/lib/config/common/jsonPath.js +44 -0
- package/lib/config/common/labjackU3T4Common.js +227 -0
- package/lib/config/common/validations.js +142 -0
- package/lib/config/configError.js +32 -0
- package/lib/config/device/adam-6052Config.js +103 -0
- package/lib/config/device/brotherHTTPConfig.js +215 -0
- package/lib/config/device/ethernetIPConfig.js +191 -0
- package/lib/config/device/ifmIotConfig.js +245 -0
- package/lib/config/device/jsonHttpConfig.js +76 -0
- package/lib/config/device/labjackT4Config.js +39 -0
- package/lib/config/device/labjackT7Config.js +192 -0
- package/lib/config/device/labjackU3Config.js +32 -0
- package/lib/config/device/modbusTcpConfig.js +336 -0
- package/lib/config/device/mqttBaseConfig.js +70 -0
- package/lib/config/device/mqttConfig.js +113 -0
- package/lib/config/device/mqttLincolnConfig.js +62 -0
- package/lib/config/device/mtconnectAdapterConfig.js +42 -0
- package/lib/config/device/mtconnectBaseConfig.js +136 -0
- package/lib/config/device/mtconnectConfig.js +52 -0
- package/lib/config/device/mtconnectHaasConfig.js +15 -0
- package/lib/config/device/nullConfig.js +81 -0
- package/lib/config/device/opcuaConfig.js +205 -0
- package/lib/config/device/pcccConfig.js +88 -0
- package/lib/config/engineConfigV1.js +382 -0
- package/lib/config/engineConfigV2.js +106 -0
- package/lib/config/generator/counterGenConfig.js +15 -0
- package/lib/config/generator/cronGenConfig.js +33 -0
- package/lib/config/generator/dateTimeGenConfig.js +33 -0
- package/lib/config/index.js +339 -0
- package/lib/config/transformConfigUtil.js +296 -0
- package/lib/engine/dataOutput.js +357 -0
- package/lib/engine/deviceOutput.js +186 -0
- package/lib/engine/engineV1.js +480 -0
- package/lib/engine/engineV2.js +719 -0
- package/lib/engine/index.js +34 -0
- package/lib/engine/transformBuilderV1.js +111 -0
- package/lib/engine/transformBuilderV2.js +74 -0
- package/lib/expressionService.js +330 -0
- package/lib/math.js +142 -0
- package/lib/transform/accumulate.js +98 -0
- package/lib/transform/average.js +56 -0
- package/lib/transform/debounce.js +152 -0
- package/lib/transform/downsample.js +69 -0
- package/lib/transform/edge.js +34 -0
- package/lib/transform/expression.js +91 -0
- package/lib/transform/fallingEdge.js +70 -0
- package/lib/transform/fromBuffer.js +89 -0
- package/lib/transform/hash.js +41 -0
- package/lib/transform/ignoreValue.js +118 -0
- package/lib/transform/index.js +93 -0
- package/lib/transform/invert.js +25 -0
- package/lib/transform/latch.js +99 -0
- package/lib/transform/latchValue.js +115 -0
- package/lib/transform/logicAnd.js +67 -0
- package/lib/transform/logicOr.js +67 -0
- package/lib/transform/map.js +115 -0
- package/lib/transform/max.js +57 -0
- package/lib/transform/maxLength.js +39 -0
- package/lib/transform/min.js +57 -0
- package/lib/transform/minDelta.js +40 -0
- package/lib/transform/offDelay.js +89 -0
- package/lib/transform/onDelay.js +89 -0
- package/lib/transform/patternEscape.js +24 -0
- package/lib/transform/patternMatch.js +194 -0
- package/lib/transform/patternReplace.js +170 -0
- package/lib/transform/patternTest.js +85 -0
- package/lib/transform/rateOfChange.js +56 -0
- package/lib/transform/reject.js +115 -0
- package/lib/transform/resample.js +96 -0
- package/lib/transform/risingEdge.js +90 -0
- package/lib/transform/risingEdgeCounter.js +179 -0
- package/lib/transform/sampleInterval.js +12 -0
- package/lib/transform/source.js +116 -0
- package/lib/transform/state.js +201 -0
- package/lib/transform/threshold.js +52 -0
- package/lib/transform/toBuffer.js +159 -0
- package/lib/transform/toggle.js +118 -0
- package/lib/transform/transformState.js +193 -0
- package/lib/transform/trim.js +27 -0
- package/lib/transform/util/chainSource.js +96 -0
- package/lib/transform/util/ringBuffer.js +34 -0
- package/lib/transform/valueChange.js +34 -0
- package/lib/transform/valueDecrease.js +38 -0
- package/lib/transform/valueIncrease.js +38 -0
- package/lib/transform/valueIncreaseDiff.js +66 -0
- package/lib/transform/whenUnavailable.js +73 -0
- package/lib/transform/windowCount.js +86 -0
- package/lib/util/fileUtil.js +44 -0
- package/package.json +38 -0
- package/test/.eslintrc.json +15 -0
- package/test/chainedTransform.test.js +88 -0
- package/test/conditions.test.js +118 -0
- package/test/config/ab-pccc.test.js +41 -0
- package/test/config/adam-6052.test.js +16 -0
- package/test/config/adapter.test.js +109 -0
- package/test/config/brother-http.test.js +19 -0
- package/test/config/ethernet-ip.test.js +19 -0
- package/test/config/ifm-iot.test.js +20 -0
- package/test/config/json-http.test.js +47 -0
- package/test/config/labjack-t4.test.js +78 -0
- package/test/config/labjack-t7.test.js +18 -0
- package/test/config/labjack-u3.test.js +17 -0
- package/test/config/modbusTcp.test.js +87 -0
- package/test/config/mqtt.test.js +19 -0
- package/test/config/mqttLincoln.test.js +29 -0
- package/test/config/mtconnect.test.js +63 -0
- package/test/config/mtconnectAdapter.test.js +124 -0
- package/test/config/mtconnectHaas.test.js +15 -0
- package/test/config/null.test.js +16 -0
- package/test/config/opcua.test.js +97 -0
- package/test/config-tests.js +102 -0
- package/test/configFiles/conditions.yml +37 -0
- package/test/configFiles/data-items-legacy.yml +24 -0
- package/test/configFiles/data-items-shorthand.yml +14 -0
- package/test/configFiles/data-items.yml +12 -0
- package/test/configFiles/device/ab-pccc-default.yml +3 -0
- package/test/configFiles/device/ab-pccc-full.yml +13 -0
- package/test/configFiles/device/adam-6052-default.yml +2 -0
- package/test/configFiles/device/brother-http-default.yml +3 -0
- package/test/configFiles/device/ethernet-ip-default.yml +2 -0
- package/test/configFiles/device/ifm-iot-default.yml +2 -0
- package/test/configFiles/device/json-http-bad-prop.yml +13 -0
- package/test/configFiles/device/json-http-bad-prop2.yml +13 -0
- package/test/configFiles/device/json-http-default.yml +3 -0
- package/test/configFiles/device/json-http-std.yml +13 -0
- package/test/configFiles/device/labjack-t4-condition-exprs.yaml +46 -0
- package/test/configFiles/device/labjack-t4-default.yml +3 -0
- package/test/configFiles/device/labjack-t4-pins-alt.yaml +41 -0
- package/test/configFiles/device/labjack-t4-pins.yaml +40 -0
- package/test/configFiles/device/labjack-t4-v1.yaml +29 -0
- package/test/configFiles/device/labjack-t7-default.yml +2 -0
- package/test/configFiles/device/labjack-u3-default.yml +2 -0
- package/test/configFiles/device/modbus-partial.yml +4 -0
- package/test/configFiles/device/modbus-std-extended.yaml +23 -0
- package/test/configFiles/device/modbus-std.yaml +34 -0
- package/test/configFiles/device/modbus-tcp-default.yml +3 -0
- package/test/configFiles/device/mqtt-default.yml +2 -0
- package/test/configFiles/device/mqtt-lincoln-default.yml +3 -0
- package/test/configFiles/device/mqtt-lincoln-full.yml +7 -0
- package/test/configFiles/device/mtconnect-adapter-default.yml +3 -0
- package/test/configFiles/device/mtconnect-adapter-keys.yaml +18 -0
- package/test/configFiles/device/mtconnect-complex-keys.yaml +17 -0
- package/test/configFiles/device/mtconnect-default.yml +3 -0
- package/test/configFiles/device/mtconnect-duplicate-allow-keys.yaml +10 -0
- package/test/configFiles/device/mtconnect-duplicate-declare-keys.yaml +8 -0
- package/test/configFiles/device/mtconnect-duplicate-deny-keys.yaml +10 -0
- package/test/configFiles/device/mtconnect-haas-default.yml +3 -0
- package/test/configFiles/device/mtconnect-std.yaml +18 -0
- package/test/configFiles/device/null-default.yml +1 -0
- package/test/configFiles/device/opcua-bad-tag.yml +18 -0
- package/test/configFiles/device/opcua-bad-tag2.yml +18 -0
- package/test/configFiles/device/opcua-default.yml +3 -0
- package/test/configFiles/device/opcua-std.yml +18 -0
- package/test/configFiles/dump-test.yml +11 -0
- package/test/configFiles/expressionCond.yml +46 -0
- package/test/configFiles/min-config-t4.yaml +4 -0
- package/test/configFiles/min-config-u3.yaml +3 -0
- package/test/configFiles/missing-device.yaml +2 -0
- package/test/configFiles/parse-error1.yml +9 -0
- package/test/configFiles/parse-error2.yml +9 -0
- package/test/configFiles/repro/buffer-convert-repro.yml +15 -0
- package/test/configFiles/repro/chained-delay-timing-repro.yml +13 -0
- package/test/configFiles/repro/count-init-repro.yml +45 -0
- package/test/configFiles/repro/cycle-break-repro.yml +44 -0
- package/test/configFiles/repro/debounce-repro.yml +46 -0
- package/test/configFiles/repro/diff-count-repro.yml +34 -0
- package/test/configFiles/repro/engine-hang-repro.yml +9 -0
- package/test/configFiles/repro/latch-apm-repro.yml +26 -0
- package/test/configFiles/repro/lockout-count-repro.yml +33 -0
- package/test/configFiles/repro/program-extract-repro.yml +38 -0
- package/test/configFiles/repro/state-latch-repro.yml +47 -0
- package/test/configFiles/repro/ternary-repro.yml +26 -0
- package/test/configFiles/transform/debounce.yml +12 -0
- package/test/configFiles/transform/expression.yml +34 -0
- package/test/configFiles/transform/ignoreValue.yml +31 -0
- package/test/configFiles/transform/latch.yml +11 -0
- package/test/configFiles/transform/latchValue.yml +31 -0
- package/test/configFiles/transform/logicAnd.yml +14 -0
- package/test/configFiles/transform/logicOr.yml +14 -0
- package/test/configFiles/transform/map.yml +19 -0
- package/test/configFiles/transform/maxLength.yml +13 -0
- package/test/configFiles/transform/offDelay.yml +12 -0
- package/test/configFiles/transform/pattern-escape.yml +10 -0
- package/test/configFiles/transform/pattern-match.yml +57 -0
- package/test/configFiles/transform/pattern-replace.yml +34 -0
- package/test/configFiles/transform/pattern-test.yml +25 -0
- package/test/configFiles/transform/reject.yml +24 -0
- package/test/configFiles/transform/risingEdgeCounter.yml +36 -0
- package/test/configFiles/transform/source.yml +20 -0
- package/test/configFiles/transform/state.yml +56 -0
- package/test/configFiles/transform/toggle.yml +19 -0
- package/test/configFiles/transform/whenUnavailable.yml +19 -0
- package/test/dataFiles/noisy-pulse.txt +11330 -0
- package/test/dataItems.test.js +140 -0
- package/test/engine-v1-tests.js +418 -0
- package/test/engine-v2-tests.js +284 -0
- package/test/expression-tests.js +171 -0
- package/test/expressionService.test.js +154 -0
- package/test/expressionServiceCondition.test.js +130 -0
- package/test/repro/buffer-convert-repro.test.js +38 -0
- package/test/repro/chained-delay-timing-repro.test.js +34 -0
- package/test/repro/count-init-repro.test.js +46 -0
- package/test/repro/cylce-break-repro.test.js +57 -0
- package/test/repro/debounce-repro.test.js +65 -0
- package/test/repro/diff-count-repro.test.js +79 -0
- package/test/repro/engine-hang-repro.test.js +38 -0
- package/test/repro/latch-apm-repro.test.js +119 -0
- package/test/repro/lockout-count-repro.test.js +84 -0
- package/test/repro/program-extract-repro.test.js +40 -0
- package/test/repro/state-latch-repro.test.js +63 -0
- package/test/repro/ternary-repro.test.js +43 -0
- package/test/transform/accumulte.test.js +18 -0
- package/test/transform/average.test.js +22 -0
- package/test/transform/debounce.test.js +70 -0
- package/test/transform/downsample.test.js +30 -0
- package/test/transform/edge.test.js +27 -0
- package/test/transform/expression.test.js +189 -0
- package/test/transform/fallingEdge.test.js +59 -0
- package/test/transform/fromBuffer.test.js +60 -0
- package/test/transform/hash.test.js +34 -0
- package/test/transform/ignoreValue.test.js +123 -0
- package/test/transform/invert.test.js +26 -0
- package/test/transform/latch.test.js +33 -0
- package/test/transform/latchValue.test.js +126 -0
- package/test/transform/logicAnd.test.js +80 -0
- package/test/transform/logicOr.test.js +80 -0
- package/test/transform/map.test.js +42 -0
- package/test/transform/max.test.js +30 -0
- package/test/transform/maxLength.test.js +32 -0
- package/test/transform/min.test.js +30 -0
- package/test/transform/minDelta.test.js +14 -0
- package/test/transform/offDelay.test.js +123 -0
- package/test/transform/onDelay.test.js +105 -0
- package/test/transform/patternEscape.test.js +18 -0
- package/test/transform/patternMatch.test.js +177 -0
- package/test/transform/patternReplace.test.js +95 -0
- package/test/transform/patternTest.test.js +105 -0
- package/test/transform/rateOfChange.test.js +34 -0
- package/test/transform/reject.test.js +56 -0
- package/test/transform/resample.test.js +193 -0
- package/test/transform/risingEdge.test.js +60 -0
- package/test/transform/risingEdgeCounter.test.js +227 -0
- package/test/transform/sampleInterval.test.js +22 -0
- package/test/transform/source.test.js +137 -0
- package/test/transform/state.test.js +248 -0
- package/test/transform/threshold.test.js +78 -0
- package/test/transform/toBuffer.test.js +60 -0
- package/test/transform/toggle.test.js +92 -0
- package/test/transform/trim.test.js +30 -0
- package/test/transform/valueChange.test.js +14 -0
- package/test/transform/valueDecrease.test.js +32 -0
- package/test/transform/valueIncrease.test.js +32 -0
- package/test/transform/valueIncreaseDiff.test.js +32 -0
- package/test/transform/whenUnavailable.test.js +93 -0
- package/test/transform/windowCount.test.js +26 -0
- package/test/util/testUtils.js +405 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ignores matching incoming value, persisting the previous unignored value instead.
|
|
8
|
+
*
|
|
9
|
+
* For every incoming sample, check if the value should be ignored (either by static equality
|
|
10
|
+
* check, pattern match, or expression evaluation). If the check passes, the value will be
|
|
11
|
+
* ignored, and the previous unignored value will be emitted instead.
|
|
12
|
+
*/
|
|
13
|
+
class IgnoreValueFilter extends TransformState {
|
|
14
|
+
constructor({ engine, path, args }) {
|
|
15
|
+
super();
|
|
16
|
+
|
|
17
|
+
this.engine = engine;
|
|
18
|
+
this.defaultValue = args.init !== undefined ? args.init : 0;
|
|
19
|
+
this.value = this.defaultValue;
|
|
20
|
+
|
|
21
|
+
if (args.expression) {
|
|
22
|
+
this.compiledExpression = args.compiledExpression;
|
|
23
|
+
this.selfSources = engine.expressionService.expressionTriggers(`${path}.expression`);
|
|
24
|
+
} else if (args.pattern) {
|
|
25
|
+
this.pattern = new RegExp(args.pattern, args.flags);
|
|
26
|
+
} else {
|
|
27
|
+
this.equalityTest = String(args.value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static op = 'ignore-value';
|
|
32
|
+
|
|
33
|
+
static create(args) {
|
|
34
|
+
return new IgnoreValueFilter(args);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static parseConfig(configUtil, defn) {
|
|
38
|
+
configUtil.requireObjectParams(defn.args, this.op, {
|
|
39
|
+
optional: false,
|
|
40
|
+
exclusive: true,
|
|
41
|
+
availableAttributes: ['value', 'pattern', 'expression'],
|
|
42
|
+
defaultAttribute: 'value',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const init = defn.args.default;
|
|
46
|
+
|
|
47
|
+
let expression = defn.args.expression;
|
|
48
|
+
if (!_.isEmpty(expression)) {
|
|
49
|
+
expression = expression.toString();
|
|
50
|
+
const compiledExpression = configUtil.compileExpression(expression, this.op);
|
|
51
|
+
|
|
52
|
+
defn.args = { init, expression, compiledExpression };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const pattern = defn.args.pattern;
|
|
56
|
+
if (!_.isEmpty(pattern)) {
|
|
57
|
+
defn.args = { init, ...configUtil.decomposePattern(pattern) };
|
|
58
|
+
configUtil.testPattern(defn.args.pattern, defn.args.flags, 'pattern');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const value = _.get(defn.args, 'value', defn.args[defn.func]);
|
|
62
|
+
if (!_.isUndefined(value) && !_.isObject(value) && !_.isArray(value)) {
|
|
63
|
+
defn.args = { init, value };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static getExpressions(configUtil, body, info) {
|
|
68
|
+
return configUtil.getExpressions(body, { ...info, field: 'expression' });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
filter(context, value, time) {
|
|
72
|
+
if (this.compiledExpression) {
|
|
73
|
+
this.filterExpression(context, value, time);
|
|
74
|
+
} else if (this.pattern) {
|
|
75
|
+
this.filterPattern(context, value, time);
|
|
76
|
+
} else {
|
|
77
|
+
this.filterEquality(context, value, time);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
filterExpression(context, value, time) {
|
|
82
|
+
const localState = { this: value };
|
|
83
|
+
const unavailTerm = this.selfSources.reduce((res, name) => {
|
|
84
|
+
const state = this.engine.getState(name);
|
|
85
|
+
localState[name] = state?.value;
|
|
86
|
+
return res || !state || !state.available;
|
|
87
|
+
}, false);
|
|
88
|
+
|
|
89
|
+
if (unavailTerm) {
|
|
90
|
+
this.setUnavailable(context, time);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
if (!this.compiledExpression.evaluate(localState)) {
|
|
96
|
+
this.commitValue(context, value, time);
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
// Probably a type error in one of the arguments.
|
|
100
|
+
this.recordError(context, err, time);
|
|
101
|
+
this.setUnavailable(context, time);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
filterPattern(context, value, time) {
|
|
106
|
+
if (!this.pattern.test(value)) {
|
|
107
|
+
this.commitValue(context, value, time);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
filterEquality(context, value, time) {
|
|
112
|
+
if (value?.toString() !== this.equalityTest) {
|
|
113
|
+
this.commitValue(context, value, time);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = IgnoreValueFilter;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const AccumulateFilter = require('./accumulate');
|
|
4
|
+
const AverageFilter = require('./average');
|
|
5
|
+
const DebounceFilter = require('./debounce');
|
|
6
|
+
const DownsampleFilter = require('./downsample');
|
|
7
|
+
const EdgeFilter = require('./edge');
|
|
8
|
+
const ExpressionFilter = require('./expression');
|
|
9
|
+
const FallingEdgeFilter = require('./fallingEdge');
|
|
10
|
+
const FromBufferFilter = require('./fromBuffer');
|
|
11
|
+
const HashFilter = require('./hash');
|
|
12
|
+
const IgnoreValueFilter = require('./ignoreValue');
|
|
13
|
+
const InvertFilter = require('./invert');
|
|
14
|
+
const LatchFilter = require('./latch');
|
|
15
|
+
const LatchValueFilter = require('./latchValue');
|
|
16
|
+
const LogicAndFilter = require('./logicAnd');
|
|
17
|
+
const LogicOrFilter = require('./logicOr');
|
|
18
|
+
const MapFilter = require('./map');
|
|
19
|
+
const MaxFilter = require('./max');
|
|
20
|
+
const MaxLengthFilter = require('./maxLength');
|
|
21
|
+
const MinDeltaFilter = require('./minDelta');
|
|
22
|
+
const MinFilter = require('./min');
|
|
23
|
+
const OffDelayFilter = require('./offDelay');
|
|
24
|
+
const OnDelayFilter = require('./onDelay');
|
|
25
|
+
const PatternEscapeFilter = require('./patternEscape');
|
|
26
|
+
const PatternMatchFilter = require('./patternMatch');
|
|
27
|
+
const PatternReplaceFilter = require('./patternReplace');
|
|
28
|
+
const PatternTestFilter = require('./patternTest');
|
|
29
|
+
const RateOfChangeFilter = require('./rateOfChange');
|
|
30
|
+
const RejectFilter = require('./reject');
|
|
31
|
+
const ResampleFilter = require('./resample');
|
|
32
|
+
const RisingEdgeCounterFilter = require('./risingEdgeCounter');
|
|
33
|
+
const RisingEdgeFilter = require('./risingEdge');
|
|
34
|
+
const SampleIntervalFilter = require('./sampleInterval');
|
|
35
|
+
const SourceFilter = require('./source');
|
|
36
|
+
const StateFilter = require('./state');
|
|
37
|
+
const ThresholdFilter = require('./threshold');
|
|
38
|
+
const ToBufferFilter = require('./toBuffer');
|
|
39
|
+
const ToggleFilter = require('./toggle');
|
|
40
|
+
const TrimFilter = require('./trim');
|
|
41
|
+
const ValueChangeFilter = require('./valueChange');
|
|
42
|
+
const ValueDecreaseFilter = require('./valueDecrease');
|
|
43
|
+
const ValueIncreaseFilter = require('./valueIncrease');
|
|
44
|
+
const ValueIncreaseDiffFilter = require('./valueIncreaseDiff');
|
|
45
|
+
const WhenUnavailableFilter = require('./whenUnavailable');
|
|
46
|
+
const WindowCountFilter = require('./windowCount');
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
accumulate: AccumulateFilter,
|
|
50
|
+
average: AverageFilter,
|
|
51
|
+
debounce: DebounceFilter,
|
|
52
|
+
downsample: DownsampleFilter,
|
|
53
|
+
edge: EdgeFilter,
|
|
54
|
+
expression: ExpressionFilter,
|
|
55
|
+
fallingEdge: FallingEdgeFilter,
|
|
56
|
+
fromBuffer: FromBufferFilter,
|
|
57
|
+
hash: HashFilter,
|
|
58
|
+
ignoreValue: IgnoreValueFilter,
|
|
59
|
+
invert: InvertFilter,
|
|
60
|
+
latch: LatchFilter,
|
|
61
|
+
latchValue: LatchValueFilter,
|
|
62
|
+
logicAnd: LogicAndFilter,
|
|
63
|
+
logicOr: LogicOrFilter,
|
|
64
|
+
map: MapFilter,
|
|
65
|
+
max: MaxFilter,
|
|
66
|
+
maxLength: MaxLengthFilter,
|
|
67
|
+
min: MinFilter,
|
|
68
|
+
minDelta: MinDeltaFilter,
|
|
69
|
+
offDelay: OffDelayFilter,
|
|
70
|
+
onDelay: OnDelayFilter,
|
|
71
|
+
patternEscape: PatternEscapeFilter,
|
|
72
|
+
patternMatch: PatternMatchFilter,
|
|
73
|
+
patternReplace: PatternReplaceFilter,
|
|
74
|
+
patternTest: PatternTestFilter,
|
|
75
|
+
rateOfChange: RateOfChangeFilter,
|
|
76
|
+
reject: RejectFilter,
|
|
77
|
+
resample: ResampleFilter,
|
|
78
|
+
risingEdgeCounter: RisingEdgeCounterFilter,
|
|
79
|
+
risingEdge: RisingEdgeFilter,
|
|
80
|
+
sampleInterval: SampleIntervalFilter,
|
|
81
|
+
source: SourceFilter,
|
|
82
|
+
state: StateFilter,
|
|
83
|
+
threshold: ThresholdFilter,
|
|
84
|
+
toBuffer: ToBufferFilter,
|
|
85
|
+
toggle: ToggleFilter,
|
|
86
|
+
trim: TrimFilter,
|
|
87
|
+
valueChange: ValueChangeFilter,
|
|
88
|
+
valueDecrease: ValueDecreaseFilter,
|
|
89
|
+
valueIncrease: ValueIncreaseFilter,
|
|
90
|
+
valueIncreaseDiff: ValueIncreaseDiffFilter,
|
|
91
|
+
whenUnavailable: WhenUnavailableFilter,
|
|
92
|
+
windowCount: WindowCountFilter,
|
|
93
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Inverts each sample in a digital stream.
|
|
8
|
+
*/
|
|
9
|
+
class InvertFilter extends TransformState {
|
|
10
|
+
static op = 'invert';
|
|
11
|
+
|
|
12
|
+
static create(_args) {
|
|
13
|
+
return new InvertFilter();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
filter(context, value, time) {
|
|
17
|
+
if (_.isNumber(value)) {
|
|
18
|
+
this.commitValue(context, 0 - value, time);
|
|
19
|
+
} else {
|
|
20
|
+
this.commitValue(context, !value, time);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = InvertFilter;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
// Deprecated: Use latch-value for similar behavior
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Latches the last incoming value received when the corresponding expression evaluates true
|
|
10
|
+
*
|
|
11
|
+
* Latch will transparently pass through all values, including unavailable state, when its
|
|
12
|
+
* expression evaluates false. When the expression evaluates true, all incoming values including
|
|
13
|
+
* changes in unavail state are ignored, with the stored value being re-emitted each time.
|
|
14
|
+
*/
|
|
15
|
+
class LatchFilter extends TransformState {
|
|
16
|
+
constructor({ engine, path, args: { condition = {} } }) {
|
|
17
|
+
super();
|
|
18
|
+
|
|
19
|
+
this.engine = engine;
|
|
20
|
+
this.conditionExpression = condition.compiledExpression;
|
|
21
|
+
this.conditionSources = engine.expressionService.expressionTriggers(`${path}.condition`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static op = 'latch';
|
|
25
|
+
|
|
26
|
+
static create(args) {
|
|
27
|
+
return new LatchFilter(args);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static parseConfig(configUtil, defn) {
|
|
31
|
+
const expression = _.get(defn.args, 'condition', defn.args[defn.func] ?? '').toString();
|
|
32
|
+
const compiledExpression = configUtil.compileExpression(expression, this.op);
|
|
33
|
+
|
|
34
|
+
const condition = { expression, compiledExpression };
|
|
35
|
+
|
|
36
|
+
defn.args = { condition };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static getExpressions(configUtil, body, info) {
|
|
40
|
+
return configUtil.getExpressions(body, { ...info, field: 'condition' }, true);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
update(context, value, time) {
|
|
44
|
+
if (this.checkConditionUnavail(context, value, time)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (this.checkCondition(context, value, time)) {
|
|
49
|
+
if (this.available) {
|
|
50
|
+
this.lastSuppliedValue = value;
|
|
51
|
+
this.lastSampleTime = time;
|
|
52
|
+
|
|
53
|
+
this.emitUpdate(context);
|
|
54
|
+
} else {
|
|
55
|
+
this.emit('unavailable', this.valueTime, context);
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (value === 'UNAVAILABLE') {
|
|
61
|
+
this.setUnavailable(context, time);
|
|
62
|
+
} else {
|
|
63
|
+
super.update(context, value, time);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
checkConditionUnavail(context, value, time) {
|
|
68
|
+
const unavailTerm = _.reduce(this.conditionSources, (res, name) => {
|
|
69
|
+
const state = this.engine.getState(name);
|
|
70
|
+
return res || !state || !state.available;
|
|
71
|
+
}, false);
|
|
72
|
+
|
|
73
|
+
if (unavailTerm) {
|
|
74
|
+
this.setUnavailable(context, time);
|
|
75
|
+
this.valueTime = time;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
checkCondition(context, value, time) {
|
|
83
|
+
try {
|
|
84
|
+
let scope = this.engine.currentState();
|
|
85
|
+
if (!this.origin) {
|
|
86
|
+
scope = { ...scope, this: value };
|
|
87
|
+
}
|
|
88
|
+
return this.conditionExpression.evaluate(scope);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
// Probably a type error in one of the arguments.
|
|
91
|
+
this.recordError(context, err, time);
|
|
92
|
+
this.setUnavailable(context, time);
|
|
93
|
+
this.valueTime = time;
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = LatchFilter;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Latches an incoming value until the reset condition is met
|
|
8
|
+
*
|
|
9
|
+
* If the latch is in an open state, the first incoming value will close the latch,
|
|
10
|
+
* and for every subseqeunt incoming value, the latch will re-emit its held value.
|
|
11
|
+
*
|
|
12
|
+
* The latch has additional options to either delay closing the latch until the incoming
|
|
13
|
+
* value is different than the previous observed value, and to set its held value to a
|
|
14
|
+
* specified default whenever the reset condition is active.
|
|
15
|
+
*/
|
|
16
|
+
class LatchValueFilter extends TransformState {
|
|
17
|
+
constructor({ engine, path, args }) {
|
|
18
|
+
super();
|
|
19
|
+
|
|
20
|
+
this.engine = engine;
|
|
21
|
+
this.resetExpression = args.reset?.compiledExpression;
|
|
22
|
+
this.resetSources = engine.expressionService.expressionTriggers(`${path}.reset`);
|
|
23
|
+
this.latchOnChange = args.latchOnChange;
|
|
24
|
+
|
|
25
|
+
this.hasResetValue = args.resetValue !== undefined;
|
|
26
|
+
if (this.hasResetValue) {
|
|
27
|
+
this.resetValue = args.resetValue;
|
|
28
|
+
this.defaultValue = this.resetValue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.initReset();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static op = 'latch-value';
|
|
35
|
+
|
|
36
|
+
static create(args) {
|
|
37
|
+
return new LatchValueFilter(args);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static parseConfig(configUtil, defn) {
|
|
41
|
+
configUtil.requireObjectParams(defn.args, this.op, {
|
|
42
|
+
optional: true,
|
|
43
|
+
availableAttributes: ['reset', 'reset-value', 'latch-on-change'],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
let latchOnChange = _.get(defn.args, 'latch-on-change');
|
|
47
|
+
if (!_.isUndefined(latchOnChange)) {
|
|
48
|
+
latchOnChange = configUtil.parseBool(latchOnChange);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const resetValue = _.get(defn.args, 'reset-value');
|
|
52
|
+
|
|
53
|
+
let reset = _.get(defn.args, 'reset');
|
|
54
|
+
if (!_.isUndefined(reset)) {
|
|
55
|
+
try {
|
|
56
|
+
const expression = reset.toString();
|
|
57
|
+
const compiledExpression = configUtil.compileExpression(expression, this.op);
|
|
58
|
+
reset = { expression, compiledExpression };
|
|
59
|
+
} catch (err) {
|
|
60
|
+
configUtil.throwConfigError(`Problem evaluating expression: ${err.message}`, this.op);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
defn.args = { latchOnChange, reset, resetValue };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static getExpressions(configUtil, body, info) {
|
|
68
|
+
return configUtil.getExpressions(body, { ...info, field: 'reset' });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
initReset() {
|
|
72
|
+
this.value = this.defaultValue;
|
|
73
|
+
this.previousValue = this.defaultValue;
|
|
74
|
+
this.previousInputValue = this.defaultValue;
|
|
75
|
+
this.latchValue = this.defaultValue;
|
|
76
|
+
this.open = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
filter(context, value, time) {
|
|
80
|
+
let resetResult = false;
|
|
81
|
+
|
|
82
|
+
if (this.resetExpression) {
|
|
83
|
+
const localState = { this: this.value };
|
|
84
|
+
const unavailTerm = this.resetSources.reduce((res, name) => {
|
|
85
|
+
const state = this.engine.getState(name);
|
|
86
|
+
localState[name] = state?.value;
|
|
87
|
+
return res || !state || !state.available;
|
|
88
|
+
}, false);
|
|
89
|
+
|
|
90
|
+
if (!unavailTerm && this.resetExpression.evaluate(localState)) {
|
|
91
|
+
this.open = true;
|
|
92
|
+
resetResult = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (this.open) {
|
|
97
|
+
let changed = this.latchValue !== value;
|
|
98
|
+
if (this.hasResetValue && !this.latchOnChange) {
|
|
99
|
+
changed = this.value !== value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const commitValue = resetResult && this.hasResetValue ? this.resetValue : value;
|
|
103
|
+
this.latchValue = value;
|
|
104
|
+
if (resetResult || changed) {
|
|
105
|
+
this.commitValue(context, commitValue, time);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!this.latchOnChange || changed) {
|
|
109
|
+
this.open = resetResult;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = LatchValueFilter;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Performs logical AND with incoming value and the result of a pre-parsed mathjs expression.
|
|
8
|
+
*
|
|
9
|
+
* Filter must be provided with the backing engine to have access to current variable states, which can
|
|
10
|
+
* be referenced in expressions by name.
|
|
11
|
+
*/
|
|
12
|
+
class LogicAndFilter extends TransformState {
|
|
13
|
+
constructor({ engine, path, args: { compiledExpression } }) {
|
|
14
|
+
super();
|
|
15
|
+
|
|
16
|
+
this.engine = engine;
|
|
17
|
+
this.expression = compiledExpression;
|
|
18
|
+
this.selfSources = engine.expressionService.expressionTriggers(path);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static op = 'logic-and';
|
|
22
|
+
|
|
23
|
+
static opAliases = ['and'];
|
|
24
|
+
|
|
25
|
+
static create(args) {
|
|
26
|
+
return new LogicAndFilter(args);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static parseConfig(configUtil, defn) {
|
|
30
|
+
const expression = (defn.args[defn.func] ?? '').toString();
|
|
31
|
+
const compiledExpression = configUtil.compileExpression(expression, this.op);
|
|
32
|
+
|
|
33
|
+
defn.args = { expression, compiledExpression };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static getExpressions(configUtil, body, info) {
|
|
37
|
+
return configUtil.getExpressions(body, info);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
filter(context, value, time) {
|
|
41
|
+
const localState = {};
|
|
42
|
+
const unavailTerm = _.reduce(this.selfSources, (res, name) => {
|
|
43
|
+
const state = this.engine.getState(name);
|
|
44
|
+
localState[name] = state?.value;
|
|
45
|
+
return res || !state || !state.available;
|
|
46
|
+
}, false);
|
|
47
|
+
|
|
48
|
+
if (unavailTerm) {
|
|
49
|
+
this.setUnavailable(context, time);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!value) {
|
|
54
|
+
this.commitValue(context, false, time);
|
|
55
|
+
} else {
|
|
56
|
+
try {
|
|
57
|
+
this.commitValue(context, this.expression.evaluate(localState), time);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
// Probably a type error in one of the arguments.
|
|
60
|
+
this.recordError(context, err, time);
|
|
61
|
+
this.setUnavailable(context, time);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = LogicAndFilter;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Performs logical OR with incoming value and the result of a pre-parsed mathjs expression.
|
|
8
|
+
*
|
|
9
|
+
* Filter must be provided with the backing engine to have access to current variable states, which can
|
|
10
|
+
* be referenced in expressions by name.
|
|
11
|
+
*/
|
|
12
|
+
class LogicOrFilter extends TransformState {
|
|
13
|
+
constructor({ engine, path, args: { compiledExpression } }) {
|
|
14
|
+
super();
|
|
15
|
+
|
|
16
|
+
this.engine = engine;
|
|
17
|
+
this.expression = compiledExpression;
|
|
18
|
+
this.selfSources = engine.expressionService.expressionTriggers(path);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static op = 'logic-or';
|
|
22
|
+
|
|
23
|
+
static opAliases = ['or'];
|
|
24
|
+
|
|
25
|
+
static create(args) {
|
|
26
|
+
return new LogicOrFilter(args);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static parseConfig(configUtil, defn) {
|
|
30
|
+
const expression = (defn.args[defn.func] ?? '').toString();
|
|
31
|
+
const compiledExpression = configUtil.compileExpression(expression, this.op);
|
|
32
|
+
|
|
33
|
+
defn.args = { expression, compiledExpression };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static getExpressions(configUtil, body, info) {
|
|
37
|
+
return configUtil.getExpressions(body, info);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
filter(context, value, time) {
|
|
41
|
+
const localState = {};
|
|
42
|
+
const unavailTerm = _.reduce(this.selfSources, (res, name) => {
|
|
43
|
+
const state = this.engine.getState(name);
|
|
44
|
+
localState[name] = state?.value;
|
|
45
|
+
return res || !state || !state.available;
|
|
46
|
+
}, false);
|
|
47
|
+
|
|
48
|
+
if (unavailTerm) {
|
|
49
|
+
this.setUnavailable(context, time);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (value) {
|
|
54
|
+
this.commitValue(context, true, time);
|
|
55
|
+
} else {
|
|
56
|
+
try {
|
|
57
|
+
this.commitValue(context, this.expression.evaluate(localState), time);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
// Probably a type error in one of the arguments.
|
|
60
|
+
this.recordError(context, err, time);
|
|
61
|
+
this.setUnavailable(context, time);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = LogicOrFilter;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const TransformState = require('./transformState');
|
|
5
|
+
|
|
6
|
+
class MapChain {
|
|
7
|
+
constructor(chain) {
|
|
8
|
+
this.chain = chain;
|
|
9
|
+
this.opResult = null;
|
|
10
|
+
|
|
11
|
+
const end = this.chain.chainEnd();
|
|
12
|
+
end.on('update', (value /* , valueTime, avail */) => {
|
|
13
|
+
this.opResult = value;
|
|
14
|
+
});
|
|
15
|
+
end.on('unavailable', (/* time */) => {
|
|
16
|
+
this.opResult = null;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
update(context, value, time) {
|
|
21
|
+
this.chain.update(context, value, time);
|
|
22
|
+
return this.opResult;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
probe(context, time) {
|
|
26
|
+
this.chain.probe(context, time);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
probeOrForward(context, time) {
|
|
30
|
+
this.chain.probeOrForward(context, time);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setUnavailable(context, time) {
|
|
34
|
+
this.chain.setUnavailable(context, time);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Executes a subprogram (chain of transforms) for each element in an incoming update.
|
|
40
|
+
*
|
|
41
|
+
* Map is intended to work on updates that contain an array of data, and is one of the few transforms to
|
|
42
|
+
* be able to support arrays. A separate transform chain instance will be maintained for each element
|
|
43
|
+
* in the array, with the assumption that the length of the incoming array will stay consistent. If the
|
|
44
|
+
* length changes, all states will be discarded and new ones will be generated.
|
|
45
|
+
*/
|
|
46
|
+
class MapFilter extends TransformState {
|
|
47
|
+
constructor({ engine, /* path, rootPath, baseTransform, */ args: { transforms } }, builder) {
|
|
48
|
+
super();
|
|
49
|
+
|
|
50
|
+
this.chain = builder.createTransformChain(engine, transforms);
|
|
51
|
+
|
|
52
|
+
this.makeChain = () => {
|
|
53
|
+
return new MapChain(builder.createTransformChain(engine, transforms));
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
this.defaultValue = [];
|
|
57
|
+
this.initReset();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static op = 'map';
|
|
61
|
+
|
|
62
|
+
static create(args) {
|
|
63
|
+
return new MapFilter(args, args.builder);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static parseConfig(configUtil, defn) {
|
|
67
|
+
if (!_.isArray(defn.args)) {
|
|
68
|
+
configUtil.throwConfigError('map must contain a list of operations', this.op);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const transforms = configUtil.loadTransformList(defn.args, defn.path, false).transform;
|
|
72
|
+
defn.args = { transforms };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
initReset() {
|
|
76
|
+
this.chainList = [];
|
|
77
|
+
this.value = [];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
supportsPendingChanges() {
|
|
81
|
+
return this.chain.supportsPendingChanges();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
updateChainList(size) {
|
|
85
|
+
if (this.chainList.length === size) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.chainList = _.times(size, () => this.makeChain());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
update(context, value, time) {
|
|
93
|
+
if (value === 'UNAVAILABLE') {
|
|
94
|
+
this.setUnavailable(context, time);
|
|
95
|
+
} else {
|
|
96
|
+
super.update(context, value, time);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
filter(context, value, time) {
|
|
101
|
+
this.updateChainList(value.length);
|
|
102
|
+
const mappedValue = _.map(_.zip(value, this.chainList), ([subValue, chain]) => {
|
|
103
|
+
return chain.update(context, subValue, time);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
this.commitValue(context, mappedValue, time);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
setUnavailable(context, time) {
|
|
110
|
+
super.setUnavailable(context, time);
|
|
111
|
+
this.initReset();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = MapFilter;
|