@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,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const expect = require('chai').expect;
|
|
4
|
+
const EngineV2 = require('../lib/engine/engineV2');
|
|
5
|
+
const Builder = require('../lib/engine/transformBuilderV2');
|
|
6
|
+
const DataOutput = require('../lib/engine/dataOutput');
|
|
7
|
+
const testUtils = require('./util/testUtils');
|
|
8
|
+
|
|
9
|
+
describe('data items', async function () {
|
|
10
|
+
let config;
|
|
11
|
+
before(async () => {
|
|
12
|
+
config = await testUtils.loadConfig('data-items.yml');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('captures simple data items', async function () {
|
|
16
|
+
const source = testUtils.valueSource();
|
|
17
|
+
const captured = makeDataOutput(config, source);
|
|
18
|
+
|
|
19
|
+
source.sendValue('key1', 'test', 2);
|
|
20
|
+
source.sendValue('key2', 2, 3);
|
|
21
|
+
source.sendValue('key2', 4, 4);
|
|
22
|
+
|
|
23
|
+
expect(captured.length).to.eq(5);
|
|
24
|
+
validateData(captured[2], 'key1', 'test', 2000);
|
|
25
|
+
validateData(captured[3], 'keymod', false, 3000);
|
|
26
|
+
validateData(captured[4], 'keymod', true, 4000);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('captures unavail data items', async function () {
|
|
30
|
+
const source = testUtils.valueSource();
|
|
31
|
+
const captured = makeDataOutput(config, source);
|
|
32
|
+
|
|
33
|
+
source.sendValue('key1', 'test', 2);
|
|
34
|
+
source.sendValue('key2', 2, 3);
|
|
35
|
+
source.unavailable(6);
|
|
36
|
+
|
|
37
|
+
expect(captured.length).to.eq(6);
|
|
38
|
+
validateData(captured[2], 'key1', 'test', 2000);
|
|
39
|
+
validateData(captured[3], 'keymod', false, 3000);
|
|
40
|
+
validateUnavail(captured[4], 'keymod', 6000);
|
|
41
|
+
validateUnavail(captured[5], 'key1', 6000);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('data items shorthand', async function () {
|
|
46
|
+
let config;
|
|
47
|
+
before(async () => {
|
|
48
|
+
config = await testUtils.loadConfig('data-items-shorthand.yml');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('captures simple data items', async function () {
|
|
52
|
+
const source = testUtils.valueSource();
|
|
53
|
+
const captured = makeDataOutput(config, source);
|
|
54
|
+
|
|
55
|
+
source.sendValue('key1', 'test', 2);
|
|
56
|
+
source.sendValue('key2', 2, 3);
|
|
57
|
+
source.sendValue('key3', { position: 5, speed: 10 }, 5);
|
|
58
|
+
|
|
59
|
+
expect(captured.length).to.eq(11);
|
|
60
|
+
validateData(captured[5], 'key1', 'test', 2000);
|
|
61
|
+
validateData(captured[6], 'key2', 2, 3000);
|
|
62
|
+
validateUnavail(captured[7], 'key2b', 3000);
|
|
63
|
+
validateData(captured[8], 'key2a', false, 3000);
|
|
64
|
+
validateData(captured[9], 'key2b', 12, 5000);
|
|
65
|
+
validateData(captured[10], 'key3', 5, 5000);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('data items legacy', async function () {
|
|
70
|
+
let config;
|
|
71
|
+
before(async () => {
|
|
72
|
+
config = await testUtils.loadConfig('data-items-legacy.yml');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('captures data items', async function () {
|
|
76
|
+
const source = testUtils.valueSource();
|
|
77
|
+
const captured = makeDataOutput(config, source);
|
|
78
|
+
|
|
79
|
+
source.sendValue('key1', 10, 2);
|
|
80
|
+
source.sendValue('key2', 2, 3);
|
|
81
|
+
source.sendValue('key2', 4, 4);
|
|
82
|
+
source.unavailable(5);
|
|
83
|
+
|
|
84
|
+
expect(captured.length).to.eq(20);
|
|
85
|
+
validateData(captured[5], 'key1', 10, 2000);
|
|
86
|
+
validateData(captured[6], 'key1a', 15, 2000);
|
|
87
|
+
validateUnavail(captured[7], 'key1b', 2000);
|
|
88
|
+
|
|
89
|
+
validateData(captured[8], 'key1b', 12, 3000);
|
|
90
|
+
validateData(captured[9], 'key2b', 'READY', 3000);
|
|
91
|
+
validateData(captured[10], 'key2a', 'READY', 3000);
|
|
92
|
+
|
|
93
|
+
validateData(captured[11], 'key1b', 14, 4000);
|
|
94
|
+
validateData(captured[12], 'key2b', 'ACTIVE', 4000);
|
|
95
|
+
validateData(captured[13], 'key2a', 'ACTIVE', 4000);
|
|
96
|
+
|
|
97
|
+
validateUnavail(captured[14], 'key1b', 5000);
|
|
98
|
+
validateUnavail(captured[15], 'key2b', 5000);
|
|
99
|
+
validateUnavail(captured[16], 'key2a', 5000);
|
|
100
|
+
validateUnavail(captured[17], 'key1', 5000);
|
|
101
|
+
validateUnavail(captured[18], 'key1a', 5000);
|
|
102
|
+
validateUnavail(captured[19], 'key1b', 5000);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
function validateData(entry, key, value, time) {
|
|
107
|
+
expect(entry.event).to.eq('data');
|
|
108
|
+
expect(entry.key).to.eq(key);
|
|
109
|
+
expect(entry.value).to.eq(value);
|
|
110
|
+
expect(entry.time).to.eq(time);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function validateUnavail(entry, key, time) {
|
|
114
|
+
expect(entry.event).to.eq('unavailable');
|
|
115
|
+
expect(entry.key).to.eq(key);
|
|
116
|
+
expect(entry.time).to.eq(time);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function makeDataOutput(config, source) {
|
|
120
|
+
const engine = new EngineV2(config);
|
|
121
|
+
const builder = new Builder(config);
|
|
122
|
+
builder.build(engine);
|
|
123
|
+
|
|
124
|
+
const buf = [];
|
|
125
|
+
const dataOutput = new DataOutput(engine, config);
|
|
126
|
+
dataOutput.on('data', (key, value, time, meta) => {
|
|
127
|
+
buf.push({ event: 'data', key, value, time, meta });
|
|
128
|
+
});
|
|
129
|
+
dataOutput.on('data_unavailable', (key, time) => {
|
|
130
|
+
buf.push({ event: 'unavailable', key, time, });
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
engine.on('update', dataOutput.handleUpdate.bind(dataOutput));
|
|
134
|
+
engine.on('unavailable', dataOutput.handleItemUnavailable.bind(dataOutput));
|
|
135
|
+
engine.addValueSource(source);
|
|
136
|
+
|
|
137
|
+
dataOutput.initiailize();
|
|
138
|
+
|
|
139
|
+
return buf;
|
|
140
|
+
}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const EventEmitter = require('eventemitter3');
|
|
5
|
+
const expect = require('chai').expect;
|
|
6
|
+
const Config = require('../lib/config');
|
|
7
|
+
const EngineV1 = require('../lib/engine/engineV1');
|
|
8
|
+
|
|
9
|
+
describe('Analog sample process', function () {
|
|
10
|
+
it('passes through all samples', function () {
|
|
11
|
+
const labjack = newAnalogLabjack({
|
|
12
|
+
'sample-interval': 0.002,
|
|
13
|
+
});
|
|
14
|
+
const source = new ValueSource();
|
|
15
|
+
labjack.addValueSource(source);
|
|
16
|
+
|
|
17
|
+
source.sendValues('pin-0', generateAnalog([1, 1, 2, 4, 3, 3, 5, 1, 2, 1], 0.002));
|
|
18
|
+
labjack.validate([1, 0.002, 2, 0.004, 4, 0.006, 3, 0.008, 3, 0.010, 5, 0.012, 1, 0.014, 2, 0.016, 1, 0.018]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('passes through every 3rd sample', function () {
|
|
22
|
+
const labjack = newAnalogLabjack({
|
|
23
|
+
'sample-interval': 0.006,
|
|
24
|
+
});
|
|
25
|
+
const source = new ValueSource();
|
|
26
|
+
labjack.addValueSource(source);
|
|
27
|
+
|
|
28
|
+
source.sendValues('pin-0', generateAnalog([1, 1, 2, 4, 3, 3, 5, 1, 2, 1], 0.002));
|
|
29
|
+
labjack.validate([4, 0.006, 5, 0.012, 1, 0.018]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('passes through sliding min', function () {
|
|
33
|
+
const labjack = newAnalogLabjack({
|
|
34
|
+
'sample-interval': 0.002,
|
|
35
|
+
'sample-function': 'min',
|
|
36
|
+
'sample-window': 0.008,
|
|
37
|
+
});
|
|
38
|
+
const source = new ValueSource();
|
|
39
|
+
labjack.addValueSource(source);
|
|
40
|
+
|
|
41
|
+
source.sendValues('pin-0', generateAnalog([1, 1, 2, 4, 3, 3, 5, 1, 2, 1], 0.002));
|
|
42
|
+
labjack.validate([0, 0.002, 0, 0.004, 1, 0.006, 1, 0.008, 2, 0.010, 3, 0.012, 1, 0.014, 1, 0.016, 1, 0.018]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('passes through sliding max', function () {
|
|
46
|
+
const labjack = newAnalogLabjack({
|
|
47
|
+
'sample-interval': 0.002,
|
|
48
|
+
'sample-function': 'max',
|
|
49
|
+
'sample-window': 0.008,
|
|
50
|
+
});
|
|
51
|
+
const source = new ValueSource();
|
|
52
|
+
labjack.addValueSource(source);
|
|
53
|
+
|
|
54
|
+
source.sendValues('pin-0', generateAnalog([1, 1, 2, 4, 3, 3, 5, 1, 2, 1], 0.002));
|
|
55
|
+
labjack.validate([1, 0.002, 2, 0.004, 4, 0.006, 4, 0.008, 4, 0.010, 5, 0.012, 5, 0.014, 5, 0.016, 5, 0.018]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('passes through sliding avg', function () {
|
|
59
|
+
const labjack = newAnalogLabjack({
|
|
60
|
+
'sample-interval': 0.002,
|
|
61
|
+
'sample-function': 'avg',
|
|
62
|
+
'sample-window': 0.008,
|
|
63
|
+
});
|
|
64
|
+
const source = new ValueSource();
|
|
65
|
+
labjack.addValueSource(source);
|
|
66
|
+
|
|
67
|
+
source.sendValues('pin-0', generateAnalog([1, 1, 2, 4, 3, 3, 5, 1, 2, 1], 0.002));
|
|
68
|
+
labjack.validate([
|
|
69
|
+
0.5, 0.002, 1, 0.004, 2, 0.006, 2.5, 0.008, 3, 0.010, 3.75, 0.012, 3, 0.014, 2.75, 0.016, 2.25, 0.018
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('passes through changes greater than min-delta', function () {
|
|
74
|
+
// Will also pass through immediately preceding sample to "step" the signal, if preceding sample was not passed
|
|
75
|
+
const labjack = newAnalogLabjack({
|
|
76
|
+
'sample-interval': 0.002,
|
|
77
|
+
'min-delta': 1.5,
|
|
78
|
+
});
|
|
79
|
+
const source = new ValueSource();
|
|
80
|
+
labjack.addValueSource(source);
|
|
81
|
+
|
|
82
|
+
source.sendValues('pin-0', generateAnalog([1, 1, 2, 4, 3, 3, 5, 1, 2, 1], 0.002));
|
|
83
|
+
labjack.validate([2, 0.004, 4, 0.006, 4, 0.012, 1, 0.014]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('passes through changes greater than min-delta with skipping interval', function () {
|
|
87
|
+
// Will also pass through immediately preceding sample to "step" the signal, if preceding sample was not passed
|
|
88
|
+
const labjack = newAnalogLabjack({
|
|
89
|
+
'sample-interval': 0.004,
|
|
90
|
+
'min-delta': 1.5,
|
|
91
|
+
});
|
|
92
|
+
const source = new ValueSource();
|
|
93
|
+
labjack.addValueSource(source);
|
|
94
|
+
|
|
95
|
+
source.sendValues('pin-0', generateAnalog([1.04, 1.11, 1.08, 4.01, 3.99, 4.04, 4.15, 1.15, 1.05, 1.1, 4.08, 4.12, 4.09], 0.002));
|
|
96
|
+
labjack.validate([3.99, 0.008, 3.99, 0.014, 1.05, 0.016, 1.05, 0.018, 4.08, 0.020]);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('Digital sample processing', function () {
|
|
101
|
+
it('raises events on transitions', function () {
|
|
102
|
+
const labjack = newDigitalLabjack();
|
|
103
|
+
const source = new ValueSource();
|
|
104
|
+
labjack.addValueSource(source);
|
|
105
|
+
|
|
106
|
+
source.sendValues('pin-0', generate('__^^^^__^^^^_____^___', 0.25));
|
|
107
|
+
labjack.validate([true, 0.5, false, 1.5, true, 2, false, 3, true, 4.25, false, 4.5]);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('raises events for inverted', function () {
|
|
111
|
+
const labjack = newDigitalLabjack({
|
|
112
|
+
invert: true,
|
|
113
|
+
});
|
|
114
|
+
const source = new ValueSource();
|
|
115
|
+
labjack.addValueSource(source);
|
|
116
|
+
|
|
117
|
+
source.sendValues('pin-0', generate('__^^^^__^^^^_____^___', 0.25)); // implicit true @ 0 event
|
|
118
|
+
labjack.validate([true, 0, false, 0.5, true, 1.5, false, 2, true, 3, false, 4.25, true, 4.5]);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('filters out <= 0.25s blips', function () {
|
|
122
|
+
const labjack = newDigitalLabjack({
|
|
123
|
+
filter: 0.25, // also delays output by 0.25
|
|
124
|
+
});
|
|
125
|
+
const source = new ValueSource();
|
|
126
|
+
labjack.addValueSource(source);
|
|
127
|
+
|
|
128
|
+
source.sendValues('pin-0', generate('____^_^^____^^^_^^__^___^^^', 0.25));
|
|
129
|
+
labjack.validate([true, 1.75, false, 2.25, true, 3.25, false, 4.75, true, 6.25]);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('filters out <= 0.5s blips', function () {
|
|
133
|
+
const labjack = newDigitalLabjack({
|
|
134
|
+
filter: 0.5, // also delays output by 0.5
|
|
135
|
+
});
|
|
136
|
+
const source = new ValueSource();
|
|
137
|
+
labjack.addValueSource(source);
|
|
138
|
+
|
|
139
|
+
source.sendValues('pin-0', generate('____^_^^____^^^_^^__^___^^^', 0.25));
|
|
140
|
+
labjack.validate([true, 3.5, false, 5.75, true, 6.5]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('delays on-state by 1s', function () {
|
|
144
|
+
const labjack = newDigitalLabjack({
|
|
145
|
+
'on-delay': 1,
|
|
146
|
+
});
|
|
147
|
+
const source = new ValueSource();
|
|
148
|
+
labjack.addValueSource(source);
|
|
149
|
+
|
|
150
|
+
source.sendValues('pin-0', generate('__^^_^^_^^^^^__^^__^^^^^^^', 0.25));
|
|
151
|
+
labjack.validate([true, 3, false, 3.25, true, 5.75]);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('delays off-state by 1s', function () {
|
|
155
|
+
const labjack = newDigitalLabjack({
|
|
156
|
+
'off-delay': 1,
|
|
157
|
+
});
|
|
158
|
+
const source = new ValueSource();
|
|
159
|
+
labjack.addValueSource(source);
|
|
160
|
+
|
|
161
|
+
source.sendValues('pin-0', generate('__^__^_^^^______^^__^^______', 0.25));
|
|
162
|
+
labjack.validate([true, 0.5, false, 3.5, true, 4, false, 6.5]);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('delays on-state by 1s with 0.25s filter', function () {
|
|
166
|
+
const labjack = newDigitalLabjack({
|
|
167
|
+
'on-delay': 1,
|
|
168
|
+
filter: 0.25,
|
|
169
|
+
});
|
|
170
|
+
const source = new ValueSource();
|
|
171
|
+
labjack.addValueSource(source);
|
|
172
|
+
|
|
173
|
+
source.sendValues('pin-0', generate('__^^_^^_^^^^^__^^__^^^^^^^', 0.25));
|
|
174
|
+
labjack.validate([true, 1.5, false, 3.5, true, 5.75]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('delays off-state by 1s with 0.25s filter', function () {
|
|
178
|
+
const labjack = newDigitalLabjack({
|
|
179
|
+
'off-delay': 1,
|
|
180
|
+
filter: 0.25,
|
|
181
|
+
});
|
|
182
|
+
const source = new ValueSource();
|
|
183
|
+
labjack.addValueSource(source);
|
|
184
|
+
|
|
185
|
+
source.sendValues('pin-0', generate('__^^__^__^______^^__^^________', 0.25));
|
|
186
|
+
labjack.validate([true, 0.75, false, 2, true, 4.25, false, 6.5]);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('holds on-state for 1s since last on-transition', function () {
|
|
190
|
+
const labjack = newDigitalLabjack({
|
|
191
|
+
'on-latch': 1,
|
|
192
|
+
});
|
|
193
|
+
const source = new ValueSource();
|
|
194
|
+
labjack.addValueSource(source);
|
|
195
|
+
|
|
196
|
+
source.sendValues('pin-0', generate('__^^__^__^______^^^^^^^__^^________', 0.25));
|
|
197
|
+
labjack.validate([true, 0.5, false, 3.25, true, 4, false, 5, true, 6.25, false, 7.25]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('holds off-state for 1s since last off-transition', function () {
|
|
201
|
+
const labjack = newDigitalLabjack({
|
|
202
|
+
'off-latch': 1,
|
|
203
|
+
});
|
|
204
|
+
const source = new ValueSource();
|
|
205
|
+
labjack.addValueSource(source);
|
|
206
|
+
|
|
207
|
+
source.sendValues('pin-0', generate('__^^__^__^______^^^^^^^__^^________', 0.25));
|
|
208
|
+
labjack.validate([true, 0.5, false, 1, true, 3.5, false, 5.75, true, 7.75]);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
describe('Counter sample processing', function () {
|
|
213
|
+
it('counts rising edges', function () {
|
|
214
|
+
const labjack = newCounterLabjack('rising');
|
|
215
|
+
const source = new ValueSource();
|
|
216
|
+
labjack.addValueSource(source);
|
|
217
|
+
|
|
218
|
+
source.sendValues('pin-0', generate('__^_^^___^_^_', 0.25));
|
|
219
|
+
labjack.validate([1, 0.5, 2, 1, 3, 2.25, 4, 2.75]);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('counts falling edges', function () {
|
|
223
|
+
const labjack = newCounterLabjack('falling');
|
|
224
|
+
const source = new ValueSource();
|
|
225
|
+
labjack.addValueSource(source);
|
|
226
|
+
|
|
227
|
+
source.sendValues('pin-0', generate('__^_^^___^_^_', 0.25));
|
|
228
|
+
labjack.validate([1, 0.75, 2, 1.5, 3, 2.5, 4, 3]);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('counts both edges', function () {
|
|
232
|
+
const labjack = newCounterLabjack('both');
|
|
233
|
+
const source = new ValueSource();
|
|
234
|
+
labjack.addValueSource(source);
|
|
235
|
+
|
|
236
|
+
source.sendValues('pin-0', generate('__^_^^___^_^_', 0.25));
|
|
237
|
+
labjack.validate([1, 0.5, 2, 0.75, 3, 1, 4, 1.5, 5, 2.25, 6, 2.5, 7, 2.75, 8, 3]);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('counts rising edge pulses >= 0.5', function () {
|
|
241
|
+
const labjack = newCounterLabjack('rising', {
|
|
242
|
+
'min-pulse-width': 0.5,
|
|
243
|
+
});
|
|
244
|
+
const source = new ValueSource();
|
|
245
|
+
labjack.addValueSource(source);
|
|
246
|
+
|
|
247
|
+
source.sendValues('pin-0', generate('__^_^^___^_^_', 0.25));
|
|
248
|
+
labjack.validate([1, 0.5, 2, 2.25]);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('counts falling edge pulses >= 0.5', function () {
|
|
252
|
+
const labjack = newCounterLabjack('falling', {
|
|
253
|
+
'min-pulse-width': 0.5,
|
|
254
|
+
});
|
|
255
|
+
const source = new ValueSource();
|
|
256
|
+
labjack.addValueSource(source);
|
|
257
|
+
|
|
258
|
+
source.sendValues('pin-0', generate('__^_^^___^^^_^_', 0.25));
|
|
259
|
+
labjack.validate([1, 1.5, 2, 3]);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('counts rising edge pulses <= 0.5', function () {
|
|
263
|
+
const labjack = newCounterLabjack('rising', {
|
|
264
|
+
'max-pulse-width': 0.5,
|
|
265
|
+
});
|
|
266
|
+
const source = new ValueSource();
|
|
267
|
+
labjack.addValueSource(source);
|
|
268
|
+
|
|
269
|
+
source.sendValues('pin-0', generate('__^_^^___^_^_', 0.25));
|
|
270
|
+
labjack.validate([1, 0.5, 2, 1, 3, 2.75]);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('counts falling edge pulses <= 0.5', function () {
|
|
274
|
+
const labjack = newCounterLabjack('falling', {
|
|
275
|
+
'max-pulse-width': 0.5,
|
|
276
|
+
});
|
|
277
|
+
const source = new ValueSource();
|
|
278
|
+
labjack.addValueSource(source);
|
|
279
|
+
|
|
280
|
+
source.sendValues('pin-0', generate('__^_^^___^^^_^_', 0.25));
|
|
281
|
+
labjack.validate([1, 0.75, 2, 1.5, 3, 3.5]);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('counts falling edges with on-delay', function () {
|
|
285
|
+
const labjack = newCounterLabjack('falling', {
|
|
286
|
+
'on-delay': 1,
|
|
287
|
+
});
|
|
288
|
+
const source = new ValueSource();
|
|
289
|
+
labjack.addValueSource(source);
|
|
290
|
+
|
|
291
|
+
source.sendValues('pin-0', generate('__^^^^^__^^__', 0.25));
|
|
292
|
+
labjack.validate([1, 1.75]);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
function newAnalogLabjack(options) {
|
|
297
|
+
options = {
|
|
298
|
+
pin: 0,
|
|
299
|
+
...options,
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const config = new Config({
|
|
303
|
+
device: 'labjack-u3',
|
|
304
|
+
input: {
|
|
305
|
+
analog: {
|
|
306
|
+
test: options,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
const processor = new EngineV1(config);
|
|
311
|
+
|
|
312
|
+
processor.events = [];
|
|
313
|
+
processor.on('update', (pin, value, time) => {
|
|
314
|
+
processor.events.push(value, time);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
processor.validate = (cmp) => {
|
|
318
|
+
expect(cmp.length).to.equal(processor.events.length);
|
|
319
|
+
for (let i = 0; i < cmp.length; i += 1) {
|
|
320
|
+
expect(Math.abs(cmp[i] - processor.events[i])).to.be.lt(0.00001);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
return processor;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function newDigitalLabjack(options) {
|
|
328
|
+
options = {
|
|
329
|
+
pin: 0,
|
|
330
|
+
'source-type': 'analog',
|
|
331
|
+
'v-threshold': 1.5,
|
|
332
|
+
...options,
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const config = new Config({
|
|
336
|
+
device: 'labjack-u3',
|
|
337
|
+
input: {
|
|
338
|
+
digital: {
|
|
339
|
+
test: options,
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
const processor = new EngineV1(config);
|
|
344
|
+
|
|
345
|
+
processor.events = [];
|
|
346
|
+
processor.on('update', (pin, value, time) => {
|
|
347
|
+
processor.events.push(value, time);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
processor.validate = (cmp) => {
|
|
351
|
+
expect(cmp).to.deep.equal(processor.events);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
return processor;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function newCounterLabjack(edge, options) {
|
|
358
|
+
options = {
|
|
359
|
+
pin: 0,
|
|
360
|
+
'source-type': 'analog',
|
|
361
|
+
'v-threshold': 1.5,
|
|
362
|
+
'trigger-edge': edge,
|
|
363
|
+
...options,
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const config = new Config({
|
|
367
|
+
device: 'labjack-u3',
|
|
368
|
+
input: {
|
|
369
|
+
counter: {
|
|
370
|
+
test: options,
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
const processor = new EngineV1(config);
|
|
375
|
+
|
|
376
|
+
processor.events = [];
|
|
377
|
+
processor.on('update', (pin, value, time) => {
|
|
378
|
+
processor.events.push(value, time);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
processor.validate = (cmp) => {
|
|
382
|
+
expect(cmp).to.deep.equal(processor.events);
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
return processor;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function generateAnalog(values, timeStep) {
|
|
389
|
+
return _.map(values, (value, time) => [value, time * timeStep]);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function generate(str, timeStep) {
|
|
393
|
+
let isHigh = false;
|
|
394
|
+
const signal = [];
|
|
395
|
+
|
|
396
|
+
for (const c of str) {
|
|
397
|
+
if (c === '^') {
|
|
398
|
+
isHigh = true;
|
|
399
|
+
signal.push(2);
|
|
400
|
+
} else if (c === '_') {
|
|
401
|
+
isHigh = false;
|
|
402
|
+
signal.push(0);
|
|
403
|
+
} else if (c === '|') {
|
|
404
|
+
isHigh = !isHigh;
|
|
405
|
+
signal.push(isHigh ? 2 : 0);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return _.map(signal, (value, time) => [value, time * timeStep]);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
class ValueSource extends EventEmitter {
|
|
413
|
+
sendValues(pin, arr) {
|
|
414
|
+
_.each(arr, ([value, time]) => {
|
|
415
|
+
this.emit('update', pin, value, time);
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|