Bladeren bron

:sparkles: adding controllers to respond to sensors | adding scanners to group controllers and logging

master
J 3 jaren geleden
bovenliggende
commit
9da5d16f00
4 gewijzigde bestanden met toevoegingen van 213 en 0 verwijderingen
  1. 55
    0
      hardware/controller.js
  2. 46
    0
      hardware/index.js
  3. 36
    0
      hardware/scanner.js
  4. 76
    0
      hardware/sensor.js

+ 55
- 0
hardware/controller.js Bestand weergeven

@@ -0,0 +1,55 @@
1
+let allWarnings = []
2
+class Warning {
3
+    constructor(msg, channelOrSensor) {
4
+        this.warning = msg
5
+        this.outOfRange = channelOrSensor.inRange
6
+        this.value = channelOrSensor.value
7
+        this.unit = channelOrSensor.unit
8
+        this.scale = channelOrSensor.scale
9
+        this.created = Date.now()
10
+    }
11
+}
12
+class Reading {
13
+    constructor({ from, value, unit, scale }) {
14
+        this.value = value
15
+        this.unit = unit
16
+        this.scale = scale
17
+        this.from = from
18
+        this.created = Date.now()
19
+    }
20
+}
21
+
22
+class Controller {
23
+    constructor({ type, channel, sensor, action=null }) {
24
+        this.type = type
25
+        this.channel = channel
26
+        this.sensor = sensor
27
+        this.action = action
28
+    }
29
+    get inRange() {
30
+        return this.channel.inRange && this.sensor.inRange
31
+    }
32
+    _checkRanges(all) {
33
+        all.forEach(channelOrSensor => {
34
+            if(channelOrSensor.inRange) return
35
+            allWarnings.push(
36
+                new Warning(`${channelOrSensor} out of range.`, channelOrSensor)
37
+            )
38
+        })
39
+    }
40
+    readout() {
41
+        const value = this.channel.readFrom(this.sensor.update())
42
+        this._checkRanges([this.channel, this.sensor])
43
+        return new Reading({
44
+            value,
45
+            from: this.channel.name,
46
+            unit:  this.channel.unit,
47
+            scale:  this.channel.scale
48
+        })
49
+    }
50
+}
51
+
52
+module.exports = {
53
+    Controller,
54
+    allWarnings
55
+}

+ 46
- 0
hardware/index.js Bestand weergeven

@@ -0,0 +1,46 @@
1
+const { TempSensor, Channel } = require('./sensor')
2
+const { Controller } = require('./controller')
3
+const { Scanner } = require('./scanner')
4
+
5
+const unitScale = {
6
+    dC: { unit: 'degree', scale: 'celcius' },
7
+    dF: { unit: 'degree', scale: 'fahrenheit' },
8
+    mV: { unit: 'volt', scale: 'millivolt' },
9
+    V: { unit: 'volt', scale: 'volt' }
10
+}
11
+
12
+/**
13
+ * Create a sensor and readout channel as -67 to 257 degrees fahrenheit
14
+ */
15
+const tempController = new Controller({
16
+    type: 'temp',
17
+    channel: new Channel({ name: 'temperature_channel_00', min: -67, max: 257, interval: 10, unit: unitScale.dF.unit, scale: unitScale.dF.scale }),
18
+    sensor: new TempSensor({ name: 'temperature_sensor_00', min: -67, max: 257, interval: 10, unit: unitScale.dF.unit, scale: unitScale.dF.scale })
19
+})
20
+console.log(tempController.readout) // { value: 78, unit: 'degrees' scale: 'fahrenheit' }
21
+
22
+/**
23
+ * Create a 0-5v sensor and interpolate readout as -67 to 257 degrees fahrenheit
24
+ */
25
+const manualTempController = new Controller({
26
+    type: 'temp',
27
+    channel: new Channel({ name: 'temperature_channel_01', min: -67, max: 257, interval: 10, unit: unitScale.dF.unit, scale: unitScale.dF.scale }),
28
+    sensor: new TempSensor({ name: 'temperature_sensor_01', min: 0, max: 5, interval: 100, unit: unitScale.mV.unit, scale: unitScale.mV.scale })
29
+})
30
+console.log(manualTempController.readout) // { value: 78, unit: 'degrees' scale: 'fahrenheit' }
31
+
32
+/**
33
+ * A Scanner is made up of controllers
34
+ * A Controller is made up of an output Channel and input Sensor
35
+ */
36
+const mySystem = new Scanner({ controllers: [ tempController, manualTempController ] })
37
+console.log(mySystem.readAll()) 
38
+/**
39
+ * Example: console.log(mySystem.readAll()) 
40
+ * temperature_channel_00: Reading({ value: 78, unit: 'degrees' scale: 'fahrenheit' }),
41
+ * temperature_channel_01: Reading({ value: 78, unit: 'degrees' scale: 'fahrenheit' }), 
42
+ */ 
43
+
44
+module.exports = {
45
+    unitScale
46
+}

+ 36
- 0
hardware/scanner.js Bestand weergeven

@@ -0,0 +1,36 @@
1
+class Scanner {
2
+    constructor({ controllers }) {
3
+        this._controllers = controllers
4
+    }
5
+    get _controllersByType() {
6
+        return this._controllers.reduce((byType, controller)=> {
7
+            const type = controller.type
8
+            if(byType[type].length < 1) byType[type] = []
9
+            byType[type].push(controller)
10
+            return byType
11
+        }, {})
12
+    }
13
+    /**
14
+     * Example: only temp controllers in range?
15
+     * const tempControlsOK = allInRange('temp')
16
+     * 
17
+     * Example: every controller in range?
18
+     * const everythingOK = allInRange()
19
+    */
20
+    allInRange(type) {
21
+        const all = type ? this._controllersByType[type] : this._controllers
22
+        return all.every(controller => controller.inRange === true)
23
+    }
24
+    readAll() {
25
+        const completeReadout = {}
26
+        this._controllers.forEach(controller => {
27
+            const readout = controller.readout()
28
+            completeReadout[readout.from] = readout
29
+        })
30
+        return completeReadout
31
+    }
32
+}
33
+
34
+module.exports = {
35
+    Scanner
36
+}

+ 76
- 0
hardware/sensor.js Bestand weergeven

@@ -0,0 +1,76 @@
1
+const { unitScale } = require('./index')
2
+
3
+const interpolate = ({ x, y, from }) => {
4
+    const [x1, x2] = x
5
+    const [y1, y2] = y
6
+    const to = y1 + (y2-y1) / (x2-x1) * (from-x1)
7
+    return to
8
+}
9
+
10
+class Base {
11
+    constructor({ name, min, max, unit, scale }) {
12
+        this.name = name
13
+        this.unit = unit
14
+        this.scale = scale
15
+        this.max = max
16
+        this.min = min
17
+        this._value = null
18
+    }
19
+    get value() { return this._value }
20
+    get aboveRange() {
21
+        return this._value > this.max
22
+    }
23
+    get belowRange() {
24
+        return this._value < this.max
25
+    }
26
+    get inRange() {
27
+        return this._value && this._value <= this.max && this._value >= this.min ? true : false
28
+    }
29
+}
30
+
31
+class Channel extends Base {
32
+    constructor({ name, min, max, interval=1, unit, scale }) {
33
+        super({ name, min: min * interval, max: max * interval, unit, scale })
34
+        this._interval = interval
35
+    }
36
+    readFrom(sensor) {
37
+        const from = sensor.value
38
+        this._value = interpolate({
39
+            x: [sensor.min, sensor.max],
40
+            y: [this.min, this.max],
41
+            from
42
+        })
43
+        return Math.round(this.value)
44
+    }
45
+}
46
+
47
+class Sensor extends Base {
48
+    constructor({ name, min, max, interval=1, unit=unitScale.mV.unit, scale=unitScale.mV.scale }) {
49
+        super({ name, min: min * interval, max: max * interval, unit, scale })
50
+        this._interval = interval
51
+    }
52
+}
53
+class TempSensor extends Sensor {
54
+    constructor({ min, max, interval, unit, scale }) {
55
+        super({ name: 'temperature_sensor', min, max, interval, unit, scale })
56
+    }
57
+    update() {
58
+        // Store data in this._value
59
+        this._value = 300
60
+        return this
61
+    }
62
+}
63
+class LevelSensor extends Sensor {
64
+    constructor({ min, max, interval=1, unit="millimeter" }) {
65
+        super({ name: 'level_sensor', min, max, interval, unit })
66
+    }
67
+    update() {
68
+        // Store data in this._value
69
+        return this
70
+    }
71
+}
72
+
73
+module.exports = {
74
+    Channel,
75
+    TempSensor,
76
+}

Laden…
Annuleren
Opslaan