UNPKG

5.13 kBJavaScriptView Raw
1const Board = require("./board");
2const Collection = require("./mixins/collection");
3const Emitter = require("events");
4const priv = new Map();
5
6
7function analogInitializer({pin}, dataHandler) {
8 const state = priv.get(this);
9
10 this.io.pinMode(pin, this.io.MODES.ANALOG);
11
12 setTimeout(() => {
13 state.isCalibrated = true;
14 this.emit("calibrated");
15 }, 10);
16
17 this.io.analogRead(pin, dataHandler);
18}
19
20const initialize = {
21 value: analogInitializer
22};
23
24const Controllers = {
25 PIR: {
26 initialize: {
27 value(options, dataHandler) {
28 const state = priv.get(this);
29 const calibrationDelay = typeof options.calibrationDelay !== "undefined" ?
30 options.calibrationDelay : 2000;
31
32 this.io.pinMode(options.pin, this.io.MODES.INPUT);
33
34 setTimeout(() => {
35 state.isCalibrated = true;
36 this.emit("calibrated");
37 }, calibrationDelay);
38
39 this.io.digitalRead(options.pin, dataHandler);
40 }
41 },
42 toBoolean: {
43 value(raw) {
44 return !!raw;
45 }
46 }
47 },
48 GP2Y0D805Z0F: {
49 ADDRESSES: {
50 value: [0x26]
51 },
52 initialize: {
53 value(options, dataHandler) {
54 const { Drivers } = require("./sip");
55 const address = Drivers.addressResolver(this, options);
56 const state = priv.get(this);
57
58 // This is meaningless for GP2Y0D805Z0F.
59 // The event is implemented for consistency
60 // with the digital passive infrared sensor
61 setTimeout(() => {
62 state.isCalibrated = true;
63 this.emit("calibrated");
64 }, 10);
65
66
67 // Set up I2C data connection
68 this.io.i2cConfig(options);
69
70 this.io.i2cWriteReg(address, 0x03, 0xFE);
71 this.io.i2cWrite(address, [0x00]);
72 this.io.i2cRead(address, 1, data => {
73 dataHandler(data[0] & 0x02);
74 });
75 }
76 },
77 toBoolean: {
78 value(raw) {
79 return raw === 0;
80 }
81 }
82 },
83 GP2Y0D810Z0F: {
84 initialize,
85 toBoolean: {
86 value(raw) {
87 return raw >> 9 === 0;
88 }
89 }
90 },
91 GP2Y0A60SZLF: {
92 initialize,
93 toBoolean: {
94 value(raw) {
95 return raw >> 9 === 1;
96 }
97 }
98 }
99};
100
101Controllers.GP2Y0D815Z0F = Controllers.GP2Y0D810Z0F;
102
103Controllers["HC-SR501"] = Controllers.PIR;
104Controllers["HCSR501"] = Controllers.PIR;
105Controllers["0D805"] = Controllers.GP2Y0D805Z0F;
106Controllers["805"] = Controllers.GP2Y0D805Z0F;
107Controllers["0D810"] = Controllers.GP2Y0D810Z0F;
108Controllers["810"] = Controllers.GP2Y0D810Z0F;
109Controllers["0D815"] = Controllers.GP2Y0D815Z0F;
110Controllers["815"] = Controllers.GP2Y0D815Z0F;
111Controllers["0A60SZLF"] = Controllers.GP2Y0A60SZLF;
112Controllers["60SZLF"] = Controllers.GP2Y0A60SZLF;
113Controllers.DEFAULT = Controllers.PIR;
114/**
115 * Motion
116 * @constructor
117 *
118 * five.Motion(7);
119 *
120 * five.Motion({
121 * controller: "PIR",
122 * pin: 7,
123 * freq: 100,
124 * calibrationDelay: 1000
125 * });
126 *
127 *
128 * @param {Object} options [description]
129 *
130 */
131
132class Motion extends Emitter {
133 constructor(options) {
134
135 super();
136
137 Board.Component.call(
138 this, options = Board.Options(options)
139 );
140
141 Board.Controller.call(this, Controllers, options);
142
143 let last = false;
144 const freq = options.freq || 25;
145 const state = {
146 value: false,
147 isCalibrated: false
148 };
149
150 priv.set(this, state);
151
152 Object.defineProperties(this, {
153 /**
154 * [read-only] Current sensor state
155 * @property detectedMotion
156 * @type Boolean
157 */
158 detectedMotion: {
159 get() {
160 return this.toBoolean(state.value);
161 }
162 },
163 /**
164 * [read-only] Sensor calibration status
165 * @property isCalibrated
166 * @type Boolean
167 */
168 isCalibrated: {
169 get() {
170 return state.isCalibrated;
171 }
172 },
173 });
174
175 if (typeof this.initialize === "function") {
176 this.initialize(options, data => state.value = data);
177 }
178
179 setInterval(() => {
180 let isChange = false;
181 const eventData = {
182 timestamp: Date.now(),
183 detectedMotion: this.detectedMotion,
184 isCalibrated: state.isCalibrated
185 };
186
187 if (state.isCalibrated && this.detectedMotion && !last) {
188 this.emit("motionstart", eventData);
189 }
190
191 if (state.isCalibrated && !this.detectedMotion && last) {
192 this.emit("motionend", eventData);
193 }
194
195 if (last !== this.detectedMotion) {
196 isChange = true;
197 }
198
199 this.emit("data", eventData);
200
201 if (isChange) {
202 this.emit("change", eventData);
203 }
204
205 last = this.detectedMotion;
206 }, freq);
207 }
208}
209
210/**
211 * Motion.Collection()
212 * new Motion.Collection()
213 *
214 * Constructs an Array-like instance
215 */
216Motion.Collection = class extends Collection.Emitter {
217 constructor(numsOrObjects) {
218 super(numsOrObjects);
219 }
220
221 get type() {
222 return Motion;
223 }
224};
225
226Collection.installMethodForwarding(
227 Motion.Collection.prototype, Motion.prototype
228);
229
230
231/* istanbul ignore else */
232if (!!process.env.IS_TEST_MODE) {
233 Motion.Controllers = Controllers;
234 Motion.purge = () => {
235 priv.clear();
236 };
237}
238
239module.exports = Motion;