UNPKG

4.84 kBJavaScriptView Raw
1const Board = require("./board");
2const Emitter = require("events");
3const { toFixed } = require("./fn");
4const priv = new Map();
5
6const Controllers = {
7 MPL3115A2: {
8 requirements: {
9 value: {
10 options: {
11 elevation: {
12 throws: false,
13 message: "Missing `elevation` option. Without a specified base `elevation`, the altitude measurement will be inaccurate. Use the meters value shown on whatismyelevation.com",
14 typeof: "number",
15 }
16 }
17 }
18 },
19 initialize: {
20 value(options, callback) {
21 const { Drivers } = require("./sip");
22 Drivers.get(this.board, "MPL3115A2", options)
23 .on("data", ({altitude}) => callback(altitude));
24 }
25 },
26 toMeters: {
27 writable: true,
28 value(value) {
29
30 // Table 2, Note 3
31 // "Smallest bit change in register represents minimum value change in
32 // Pascals or meters. Typical resolution to signify change in altitudeis 0.3 m"
33 return toFixed(value, 1);
34 }
35 }
36 },
37 MS5611: {
38 initialize: {
39 value(options, callback) {
40 const { Drivers } = require("./sip");
41 Drivers.get(this.board, "MS5611", options)
42 .on("data", ({altitude}) => callback(altitude));
43 }
44 },
45 toMeters: {
46 writable: true,
47 value(value) {
48 // Datasheet available at http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=MS5611-01BA03&DocType=Data+Sheet&DocLang=English
49 //
50 // From page 1
51 // "This barometric pressure sensor is optimized for
52 // altimeters and variometers with an altitude resolution of 10 cm."
53 return toFixed(value, 2);
54 }
55 }
56 },
57
58 BMP180: {
59 initialize: {
60 value(options, callback) {
61 const { Drivers } = require("./sip");
62 Drivers.get(this.board, "BMP180", options)
63 .on("data", ({altitude}) => callback(altitude));
64 }
65 },
66 toMeters: {
67 writable: true,
68 value(value) {
69 // Page 6, Table 1
70 // Resolution of output data 0.01hPa
71 //
72 // From paragraph 3.6, page 16 1hPa=8.43m
73 // resolution ~= 0.08m
74 return toFixed(value, 2);
75 }
76 }
77 },
78
79 BMP280: {
80 initialize: {
81 value(options, callback) {
82 const { Drivers } = require("./sip");
83 Drivers.get(this.board, "BMP280", options)
84 .on("data", ({altitude}) => callback(altitude));
85 }
86 },
87 toMeters: {
88 writable: true,
89 value(value) {
90 // Page 8, Table 2
91 // Resolution of output data in ultra high resolution mode 0.0016hPa
92 // 1hPa=8.43m
93 // resolution ~= 0.013m
94 return toFixed(value, 3);
95 }
96 }
97 },
98 BME280: {
99 initialize: {
100 value(options, callback) {
101 const { Drivers } = require("./sip");
102 Drivers.get(this.board, "BME280", options)
103 .on("data", ({altitude}) => callback(altitude));
104 }
105 },
106 toMeters: {
107 writable: true,
108 value(value) {
109 // Page 10, Table 3
110 // Resolution of pressure output data 0.18Pa
111 // 1hPa=8.43m
112 // 100Pa=8.43m
113 // resolution ~= 0.015m
114 return toFixed(value, 3);
115 }
116 }
117 },
118
119};
120
121Controllers["BMP085"] = Controllers["BMP-085"] = Controllers.BMP180;
122
123
124class Altimeter extends Emitter {
125 constructor(options) {
126 super();
127
128 Board.Component.call(
129 this, options = Board.Options(options)
130 );
131
132 Board.Controller.call(this, Controllers, options);
133
134 const state = {};
135 const freq = options.freq || 25;
136 let last = null;
137 let value = null;
138
139 if (!this.toMeters) {
140 this.toMeters = options.toMeters || (x => x);
141 }
142
143 priv.set(this, state);
144
145 const descriptors = {
146 meters: {
147 get() {
148 return this.toMeters(value);
149 }
150 },
151 feet: {
152 get() {
153 return toFixed(this.meters * 3.28084, 2);
154 }
155 }
156 };
157 // Convenience aliases
158 descriptors.m = descriptors.meters;
159 descriptors.ft = descriptors.feet;
160
161 Object.defineProperties(this, descriptors);
162
163
164 /* istanbul ignore else */
165 if (typeof this.initialize === "function") {
166 this.initialize(options, data => value = data);
167 }
168
169 setInterval(() => {
170 if (value == null) {
171 return;
172 }
173
174 const data = {};
175 data.m = data.meters = this.meters;
176 data.ft = data.feet = this.feet;
177
178 this.emit("data", data);
179
180 /* istanbul ignore else */
181 if (this.meters !== last) {
182 last = this.meters;
183 this.emit("change", data);
184 }
185 }, freq);
186 }
187}
188
189/* istanbul ignore else */
190if (!!process.env.IS_TEST_MODE) {
191 Altimeter.Controllers = Controllers;
192 Altimeter.purge = function() {
193 priv.clear();
194 };
195}
196
197
198module.exports = Altimeter;